Compare commits

...

5 commits

Author SHA1 Message Date
c6755cb585
bump: version 0.2.0 → 0.3.0
All checks were successful
Build and Release / build (push) Successful in 1m38s
2025-06-15 03:00:23 +10:00
aec0f14c68
refactor: change variable and function names to fit with golang conventions 2025-06-15 03:00:09 +10:00
3529f7e415
refactor: remove pointless else statments 2025-06-15 02:57:54 +10:00
f9575c92a9
refactor: add package string 2025-06-15 02:57:21 +10:00
1b4cd880ef
chore(gitignore): ignore .vscode settings 2025-06-15 02:54:45 +10:00
4 changed files with 61 additions and 48 deletions

View file

@ -2,6 +2,6 @@
name = "cz_conventional_commits" name = "cz_conventional_commits"
tag_format = "$version" tag_format = "$version"
version_scheme = "semver2" version_scheme = "semver2"
version = "0.2.0" version = "0.3.0"
update_changelog_on_bump = true update_changelog_on_bump = true
major_version_zero = true major_version_zero = true

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
fps-go-brr fps-go-brr
fps-go-brr-compact fps-go-brr-compact
.vscode/settings.json

View file

@ -1,3 +1,12 @@
## 0.3.0 (2025-06-15)
### Refactor
- change variable and function names to fit with golang conventions
- remove pointless else statments
- add package string
- **gitignore**: ignore compact build binary
## 0.2.0 (2025-06-14) ## 0.2.0 (2025-06-14)
### Feat ### Feat

83
main.go
View file

@ -1,3 +1,4 @@
// A Go CLI tool for video frame analysis and comparison. Analyze frame persistence, detect dropped frames, and export data for visualization tools like those used by Digital Foundry.
package main package main
import ( import (
@ -22,7 +23,7 @@ func main() {
Usage: "Count frames", Usage: "Count frames",
Action: func(ctx context.Context, cmd *cli.Command) error { Action: func(ctx context.Context, cmd *cli.Command) error {
return count_video_frames(cmd.Args().First()) return countVideoFrames(cmd.Args().First())
}, },
}, },
{ {
@ -39,12 +40,12 @@ func main() {
Action: func(ctx context.Context, cmd *cli.Command) error { Action: func(ctx context.Context, cmd *cli.Command) error {
first_frame, _ := getImageFromFilePath(cmd.StringArg("frame1")) firstFrame, _ := getImageFromFilePath(cmd.StringArg("frame1"))
second_frame, _ := getImageFromFilePath(cmd.StringArg("frame2")) secondFrame, _ := getImageFromFilePath(cmd.StringArg("frame2"))
first_rgba := imageToRGBA(first_frame) firstRGBA := imageToRGBA(firstFrame)
second_rgba := imageToRGBA(second_frame) secondRGBA := imageToRGBA(secondFrame)
return compare_frames(first_rgba, second_rgba) return compareFrames(firstRGBA, secondRGBA)
}, },
}, },
{ {
@ -61,12 +62,12 @@ func main() {
Action: func(ctx context.Context, cmd *cli.Command) error { Action: func(ctx context.Context, cmd *cli.Command) error {
first_frame, _ := getImageFromFilePath(cmd.StringArg("frame1")) firstFrame, _ := getImageFromFilePath(cmd.StringArg("frame1"))
second_frame, _ := getImageFromFilePath(cmd.StringArg("frame2")) secondFrame, _ := getImageFromFilePath(cmd.StringArg("frame2"))
first_rgba := imageToRGBA(first_frame) firstRGBA := imageToRGBA(firstFrame)
second_rgba := imageToRGBA(second_frame) secondRGBA := imageToRGBA(secondFrame)
return compare_frames_alt(first_rgba, second_rgba) return compareFramesAlt(firstRGBA, secondRGBA)
}, },
}, },
{ {
@ -119,7 +120,7 @@ func main() {
} }
} }
// count_video_frames // countVideoFrames
// Prints out the total ammount of frames within `video` // Prints out the total ammount of frames within `video`
// //
// Parameters: // Parameters:
@ -127,18 +128,18 @@ func main() {
// //
// Returns: // Returns:
// - error // - error
func count_video_frames(video string) error { func countVideoFrames(video string) error {
log.Default().Print("Trying to open video at: " + video) log.Default().Print("Trying to open video at: " + video)
video_file, _ := vidio.NewVideo(video) videoFile, _ := vidio.NewVideo(video)
count := 0 count := 0
for video_file.Read() { for videoFile.Read() {
count++ count++
} }
log.Default().Println("Video total frames: " + strconv.Itoa(count)) log.Default().Println("Video total frames: " + strconv.Itoa(count))
return nil return nil
} }
func compare_frames(frame1 *image.RGBA, frame2 *image.RGBA) error { func compareFrames(frame1 *image.RGBA, frame2 *image.RGBA) error {
accumError := int64(0) accumError := int64(0)
for i := 0; i < len(frame1.Pix); i++ { for i := 0; i < len(frame1.Pix); i++ {
@ -150,7 +151,7 @@ func compare_frames(frame1 *image.RGBA, frame2 *image.RGBA) error {
return nil return nil
} }
func compare_frames_alt(frame1 *image.RGBA, frame2 *image.RGBA) error { func compareFramesAlt(frame1 *image.RGBA, frame2 *image.RGBA) error {
// diff_frame := image.NewRGBA(frame1.Rect) // diff_frame := image.NewRGBA(frame1.Rect)
accumError := int64(0) accumError := int64(0)
for i := 0; i < len(frame1.Pix); i++ { for i := 0; i < len(frame1.Pix); i++ {
@ -172,9 +173,10 @@ func isDiffUInt8(x, y uint8) bool {
sq := d * d sq := d * d
if sq > 0 { if sq > 0 {
return true return true
} else {
return false
} }
return false
} }
func isDiffUInt8WithTolerance(x, y uint8, tolerance uint64) bool { func isDiffUInt8WithTolerance(x, y uint8, tolerance uint64) bool {
@ -182,45 +184,46 @@ func isDiffUInt8WithTolerance(x, y uint8, tolerance uint64) bool {
sq := d * d sq := d * d
if sq > tolerance { if sq > tolerance {
return true return true
} else {
return false
} }
return false
} }
func countUniqueVideoFrames(video_path1 string, video_path2 string, min_diff uint64, use_sq_diff bool) error { func countUniqueVideoFrames(videoPath1 string, videoPath2 string, minDiff uint64, useSqDiff bool) error {
video1, _ := vidio.NewVideo(video_path1) video1, _ := vidio.NewVideo(videoPath1)
video2, _ := vidio.NewVideo(video_path2) video2, _ := vidio.NewVideo(videoPath2)
video1_frame := image.NewRGBA(image.Rect(0, 0, video1.Width(), video1.Height())) video1Frame := image.NewRGBA(image.Rect(0, 0, video1.Width(), video1.Height()))
video2_frame := image.NewRGBA(image.Rect(0, 0, video2.Width(), video2.Height())) video2Frame := image.NewRGBA(image.Rect(0, 0, video2.Width(), video2.Height()))
video1.SetFrameBuffer(video1_frame.Pix) video1.SetFrameBuffer(video1Frame.Pix)
video2.SetFrameBuffer(video2_frame.Pix) video2.SetFrameBuffer(video2Frame.Pix)
total_frames := 0 totalFrames := 0
unique_frames := 0 uniqueFrames := 0
for video1.Read() { for video1.Read() {
total_frames++ totalFrames++
video2.Read() video2.Read()
accumError := uint64(0) accumError := uint64(0)
for i := 0; i < len(video1_frame.Pix); i++ { for i := 0; i < len(video1Frame.Pix); i++ {
if use_sq_diff { if useSqDiff {
if isDiffUInt8WithTolerance(video1_frame.Pix[i], video2_frame.Pix[i], min_diff) { if isDiffUInt8WithTolerance(video1Frame.Pix[i], video2Frame.Pix[i], minDiff) {
accumError++ accumError++
} }
} else { } else {
if isDiffUInt8(video1_frame.Pix[i], video2_frame.Pix[i]) { if isDiffUInt8(video1Frame.Pix[i], video2Frame.Pix[i]) {
accumError++ accumError++
} }
} }
} }
if min_diff <= accumError { if minDiff <= accumError {
unique_frames++ uniqueFrames++
log.Default().Println("[" + strconv.Itoa(total_frames) + "]Unique frame") log.Default().Println("[" + strconv.Itoa(totalFrames) + "]Unique frame")
} else { } else {
log.Default().Println("[" + strconv.Itoa(total_frames) + "]Non-unique frame") log.Default().Println("[" + strconv.Itoa(totalFrames) + "]Non-unique frame")
} }
} }
video1.Close() video1.Close()
video2.Close() video2.Close()
log.Default().Println(strconv.Itoa(unique_frames) + "/" + strconv.Itoa(total_frames) + " are unique!") log.Default().Println(strconv.Itoa(uniqueFrames) + "/" + strconv.Itoa(totalFrames) + " are unique!")
return nil return nil
} }