├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── cxgo.yml ├── example └── player │ └── main.go ├── go.mod ├── go.sum ├── mpg.go ├── pl_mpeg.go └── utils.go /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Crazyinfin8 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MPG-Go 2 | ## Pure Go mpg decoding made from [pl_mpeg] 3 | [![GoDoc](https://godoc.org/github.com/crazyinfin8/mpg-go?status.svg)](https://pkg.go.dev/github.com/crazyinfin8/mpg-go) [![GoReportCard](https://goreportcard.com/badge/github.com/crazyinfin8/mpg-go)](https://goreportcard.com/report/github.com/crazyinfin8/mpg-go) 4 | 5 | [Mpg-go] is a pure Go (no CGo) MPG decoder and player. It is made by transpiling [pl_mpeg] from C to Go using the [cxgo] translation tool. 6 | 7 | [Mpg-go]'s Goal is to provide an easy to use, pure Go software video and audio decoder. It provides functions meant for drawing frames to `image/draw`'s `Image`s, as well as writing directly to `image`'s `RGBA.Pix`, and provides and easy to use audio reader made to work effortlessly in Ebiten or Oto. For a working example project showing many features of [mpg-go], see [player]. 8 | 9 | As [pl_mpeg] and [cxgo] are both experimental, [mpg-go] should also be experimental as well. 10 | 11 | # Encoding 12 | 13 | [Pl_mpeg] supports mpg file container with MPEG1 ("mpeg1") video encoding and MPEG1 Audio Layer II ("mp2") audio encoding. While MPEG1 and MP2 is seen as outdated and inefficient, it's patents should have expired by now making it 14 | 15 | You can encode your own videos to mpg with FFMPEG using the following command: 16 | 17 | ```bash 18 | ffmpeg -i -c:v mpeg1video -c:a mp2 -q:v 0 .mpg 19 | ``` 20 | 21 | This will convert the video from `` to `.mpg` with the right codec and variable bitrate. 22 | 23 | # Getting started 24 | 25 | ## Running example 26 | To run the example, run this command: 27 | 28 | ```bash 29 | go install github.com/crazyinfin8/mpg-go/example/player@latest 30 | go run github.com/crazyinfin8/mpg-go/example/player 31 | ``` 32 | 33 | ## Install 34 | 35 | To install this library for use in your own project, run the following command: 36 | 37 | ```bash 38 | go get github.com/crazyinfin8/mpg-go 39 | ``` 40 | 41 | ## Usage 42 | 43 | A new player can be created using one of the following functions 44 | 45 | ```go 46 | import "github.com/crazyinfin8/mpg-go" 47 | 48 | player, err := mpg.NewPlayerFromFile(*io.File) 49 | player, err := mpg.NewPlayerFromFilename(string) 50 | player, err := mpg.NewPlayerFromBytes([]byte) 51 | ``` 52 | 53 | Set up your graphics library 54 | 55 | ```go 56 | import "github.com/crazyinfin8/mpg-go" 57 | import "image" 58 | 59 | if player.HasVideo() { 60 | width, height := player.Width(), player.Height() 61 | img := image.NewRGBA(image.Rect(0, 0, width, height)) 62 | 63 | // if using functions ReadRGBA and ReadRGBAAt, 64 | // set alpha channels because those functions do not set them. 65 | mpg.SetAlpha(img.Pix) 66 | } 67 | ``` 68 | 69 | Set up your audio library 70 | 71 | ```go 72 | import "github.com/hajimehoshi/ebiten/v2/audio" 73 | import "time" 74 | 75 | var ctx *audio.Context 76 | var stream *audio.Player 77 | 78 | if player.HasAudio() { 79 | samplerate := player.SampleRate() 80 | ctx = audio.NewContext(samplerate) 81 | stream = ctx.NewPlayer(player) 82 | player.SetByteDepth(2) // Ebiten uses 16-bit audio 83 | 84 | // Using default buffer size 85 | stream.SetBufferSize(player.AudioLeadTime()) 86 | 87 | //setting a custom buffer size 88 | stream.SetBufferSize(50 * time.Millisecond) 89 | player.SetAudioLeadTime(50 * time.Millisecond) 90 | 91 | stream.Play() 92 | } 93 | ``` 94 | 95 | Decode video and audio. 96 | 97 | ```go 98 | import "time" 99 | 100 | framerate := player.FrameRate() 101 | 102 | // Call this every frame to progress through and decode the video 103 | // 104 | // This moves at a fized rate for each frame, however it might be more smooth to 105 | // calculate a time delta per frame. 106 | player.Decode(time.Duration(1 / framerate * float64(time.Second))) 107 | ``` 108 | 109 | Display the video (audio using Ebiten's `audio.Player` should already be playing) 110 | 111 | ```go 112 | if player.HasNewFrame() { 113 | // Sets a pixel byte array directly. Note that the pixel array should be the 114 | // same size as the frame i.e. width*height*4. 115 | player.ReadRGBA(img.Pix) 116 | // Draws itself to a "draw.Image" 117 | player.DrawTo(img) 118 | 119 | // Audio is already playing through the Ebiten audio stream. 120 | } 121 | ``` 122 | 123 | Cleanup when finished 124 | 125 | ```go 126 | if player.Finished() { 127 | // video playback is done! 128 | } 129 | 130 | player.Close() 131 | ``` 132 | 133 | # TODO 134 | 135 | - Add functions to just decode all frames and audio. 136 | - Make it easier to use mpg-go in other graphic libraries such as SDL and Raylib. 137 | 138 | [pl_mpeg]:https://github.com/phoboslab/pl_mpeg 139 | [mpg-go]:https://pkg.go.dev/github.com/crazyinfin8/mpg-go 140 | [cxgo]:https://github.com/gotranspile/cxgo 141 | [player]:example/player/ -------------------------------------------------------------------------------- /cxgo.yml: -------------------------------------------------------------------------------- 1 | vcs: https://github.com/phoboslab/pl_mpeg 2 | 3 | root: . 4 | 5 | out: . 6 | 7 | package: mpg 8 | 9 | define: 10 | - name: PL_MPEG_IMPLEMENTATION 11 | 12 | # Generates license, copywrite, and "DO NOT EDIT" flag 13 | exec_after: 14 | [ 15 | "sed", 16 | "-i", 17 | "1s/^/\\/\\/ Code generated by go generate; DO NOT EDIT.\\n\\n\\/\\/ PL_MPEG Copywrite Dominic Szablewski\\n\\/\\/\\n\\/\\/ Permission is hereby granted, free of charge, to any person obtaining a copy of\\n\\/\\/ this software and associated documentation files(the \"Software\"), to deal in\\n\\/\\/ the Software without restriction, including without limitation the rights to\\n\\/\\/ use, copy, modify, merge, publish, distribute, sublicense, and \\/ or sell copies\\n\\/\\/ of the Software, and to permit persons to whom the Software is furnished to do\\n\\/\\/ so, subject to the following conditions :\\n\\/\\/ The above copyright notice and this permission notice shall be included in all\\n\\/\\/ copies or substantial portions of the Software.\\n\\/\\/ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n\\/\\/ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\\n\\/\\/ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\\n\\/\\/ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\\n\\/\\/ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\\n\\/\\/ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\\n\\/\\/ SOFTWARE.\\n\\n/", 18 | "pl_mpeg.go", 19 | ] 20 | 21 | # Hide C constants and variables from external Go packages for cleanliness 22 | files: 23 | - name: pl_mpeg.h 24 | replace: 25 | - old: PLM_PACKET_INVALID_TS 26 | new: plm_packet_invalid_ts1 27 | - old: PLM_AUDIO_SAMPLES_PER_FRAME 28 | new: plm_audio_samples_per_frame 29 | - old: PLM_BUFFER_DEFAULT_SIZE 30 | new: plm_buffer_default_size 31 | - old: "TRUE" 32 | new: "_true" 33 | - old: "FALSE" 34 | new: "_false" 35 | - old: PLM_DEMUX_PACKET_PRIVATE 36 | new: plm_demux_packet_private 37 | - old: PLM_DEMUX_PACKET_AUDIO_1 38 | new: plm_demux_packet_audio_1 39 | - old: PLM_DEMUX_PACKET_AUDIO_2 40 | new: plm_demux_packet_audio_2 41 | - old: PLM_DEMUX_PACKET_AUDIO_3 42 | new: plm_demux_packet_audio_3 43 | - old: PLM_DEMUX_PACKET_AUDIO_4 44 | new: plm_demux_packet_audio_4 45 | - old: PLM_DEMUX_PACKET_VIDEO_1 46 | new: plm_demux_packet_video_1 47 | - old: PLM_BUFFER_MODE_FILE 48 | new: plm_buffer_mode_file 49 | - old: PLM_BUFFER_MODE_FIXED_MEM 50 | new: plm_buffer_mode_fixed_mem 51 | - old: PLM_BUFFER_MODE_RING 52 | new: plm_buffer_mode_ring 53 | - old: PLM_BUFFER_MODE_APPEND 54 | new: plm_buffer_mode_append 55 | - old: PLM_START_PACK 56 | new: plm_start_pack 57 | - old: PLM_START_END 58 | new: plm_start_end 59 | - old: PLM_START_SYSTEM 60 | new: plm_start_system 61 | - old: PLM_VIDEO_PICTURE_TYPE_INTRA 62 | new: plm_video_picture_type_intra 63 | - old: PLM_VIDEO_PICTURE_TYPE_PREDICTIVE 64 | new: plm_video_picture_type_predictive 65 | - old: PLM_VIDEO_PICTURE_TYPE_B 66 | new: plm_video_picture_type_b 67 | - old: PLM_START_SEQUENCE 68 | new: plm_start_sequence 69 | - old: PLM_START_SLICE_FIRST 70 | new: plm_start_slice_first 71 | - old: PLM_START_SLICE_LAST 72 | new: plm_start_slice_last 73 | - old: PLM_START_PICTURE 74 | new: plm_start_picture 75 | - old: PLM_START_EXTENSION 76 | new: plm_start_extension 77 | - old: PLM_START_USER_DATA 78 | new: plm_start_user_data 79 | - old: PLM_VIDEO_PICTURE_RATE 80 | new: plm_video_picture_rate 81 | - old: PLM_VIDEO_ZIG_ZAG 82 | new: plm_video_zig_zag 83 | - old: PLM_VIDEO_INTRA_QUANT_MATRIX 84 | new: plm_video_intra_quant_matrix 85 | - old: PLM_VIDEO_NON_INTRA_QUANT_MATRIX 86 | new: plm_video_non_intra_quant_matrix 87 | - old: PLM_VIDEO_PREMULTIPLIER_MATRIX 88 | new: plm_video_premultiplier_matrix 89 | - old: PLM_VIDEO_MACROBLOCK_ADDRESS_INCREMENT 90 | new: plm_video_macroblock_address_increment 91 | - old: PLM_VIDEO_MACROBLOCK_TYPE_INTRA 92 | new: plm_video_macroblock_type_intra 93 | - old: PLM_VIDEO_MACROBLOCK_TYPE_PREDICTIVE 94 | new: plm_video_macroblock_type_predictive 95 | - old: PLM_VIDEO_MACROBLOCK_TYPE_B 96 | new: plm_video_macroblock_type_b 97 | - old: PLM_VIDEO_MACROBLOCK_TYPE 98 | new: plm_video_macroblock_type 99 | - old: PLM_VIDEO_CODE_BLOCK_PATTERN 100 | new: plm_video_code_block_pattern 101 | - old: PLM_VIDEO_MOTION 102 | new: plm_video_motion 103 | - old: PLM_VIDEO_DCT_SIZE_LUMINANCE 104 | new: plm_video_dct_size_luminance 105 | - old: PLM_VIDEO_DCT_SIZE_CHROMINANCE 106 | new: plm_video_dct_size_chrominance 107 | - old: PLM_VIDEO_DCT_SIZE 108 | new: plm_video_dct_size 109 | - old: PLM_VIDEO_DCT_COEFF 110 | new: plm_video_dct_coeff 111 | - old: PLM_AUDIO_QUANT_TAB 112 | new: plm_audio_quant_tab 113 | - old: PLM_AUDIO_FRAME_SYNC 114 | new: plm_audio_frame_sync 115 | - old: PLM_AUDIO_MPEG_2_5 116 | new: plm_audio_mpeg_2_5 117 | - old: PLM_AUDIO_MPEG_2 118 | new: plm_audio_mpeg_2 119 | - old: PLM_AUDIO_MPEG_1 120 | new: plm_audio_mpeg_1 121 | - old: PLM_AUDIO_LAYER_III 122 | new: plm_audio_layer_iii 123 | - old: PLM_AUDIO_LAYER_II 124 | new: plm_audio_layer_ii 125 | - old: PLM_AUDIO_LAYER_I 126 | new: plm_audio_layer_i 127 | - old: PLM_AUDIO_MODE_STEREO 128 | new: plm_audio_mode_stereo 129 | - old: PLM_AUDIO_MODE_JOINT_STEREO 130 | new: plm_audio_mode_joint_stereo 131 | - old: PLM_AUDIO_MODE_DUAL_CHANNEL 132 | new: plm_audio_mode_dual_channel 133 | - old: PLM_AUDIO_MODE_MONO 134 | new: plm_audio_mode_mono 135 | - old: PLM_AUDIO_SAMPLE_RATE 136 | new: plm_audio_sample_rate 137 | - old: PLM_AUDIO_BIT_RATE 138 | new: plm_audio_bit_rate 139 | - old: PLM_AUDIO_SCALEFACTOR_BASE 140 | new: plm_audio_scalefactor_base 141 | - old: PLM_AUDIO_SYNTHESIS_WINDOW 142 | new: plm_audio_synthesis_window 143 | - old: PLM_AUDIO_QUANT_LUT_STEP_1 144 | new: plm_audio_quant_lut_step_1 145 | - old: PLM_AUDIO_QUANT_TAB_A 146 | new: plm_audio_quant_tab_a 147 | - old: PLM_AUDIO_QUANT_TAB_B 148 | new: plm_audio_quant_tab_b 149 | - old: PLM_AUDIO_QUANT_TAB_C 150 | new: plm_audio_quant_tab_c 151 | - old: PLM_AUDIO_QUANT_TAB_D 152 | new: plm_audio_quant_tab_d 153 | - old: QUANT_LUT_STEP_2 154 | new: quant_lut_step_2 155 | - old: PLM_AUDIO_QUANT_LUT_STEP_3 156 | new: plm_audio_quant_lut_step_3 157 | - old: PLM_AUDIO_QUANT_LUT_STEP_4 158 | new: plm_audio_quant_lut_step_4 159 | - old: PLM_AUDIO_QUANT_TAB 160 | new: plm_audio_quant_tab 161 | -------------------------------------------------------------------------------- /example/player/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "image" 7 | "image/color" 8 | "math" 9 | "time" 10 | 11 | "github.com/crazyinfin8/mpg-go" 12 | "github.com/hajimehoshi/ebiten/v2" 13 | "github.com/hajimehoshi/ebiten/v2/audio" 14 | "github.com/hajimehoshi/ebiten/v2/ebitenutil" 15 | "github.com/hajimehoshi/ebiten/v2/inpututil" 16 | ) 17 | 18 | type Game struct { 19 | player *mpg.Player 20 | videoFrame *image.RGBA 21 | videoImage *ebiten.Image 22 | ctx *audio.Context 23 | p *audio.Player 24 | ptime time.Time 25 | 26 | playing bool 27 | loop bool 28 | debug bool 29 | scrubbing bool 30 | 31 | playheadPos float64 32 | playheadColor color.Color 33 | 34 | // TODO: try implementing preview frames when hovering over the playhead 35 | pmouseX int 36 | previewFrame *image.RGBA 37 | previewImage *ebiten.Image 38 | previewPos *ebiten.DrawImageOptions 39 | } 40 | 41 | func main() { 42 | defer func(err interface{}) { 43 | if err != nil { 44 | fmt.Printf("Recovered from panic:\n\n%#v", err) 45 | } 46 | }(recover()) 47 | 48 | var ( 49 | videoPath string 50 | err error 51 | printHelp bool 52 | ) 53 | g := new(Game) 54 | 55 | flag.BoolVar(&g.loop, "l", false, "Loop video playback") 56 | flag.BoolVar(&g.loop, "loop", false, "Loop video playback") 57 | flag.StringVar(&videoPath, "p", "", "Path to MPG file") 58 | flag.StringVar(&videoPath, "path", "", "Path to MPG file") 59 | flag.BoolVar(&g.debug, "debug", false, "prints statistics to the screen") 60 | flag.BoolVar(&g.debug, "d", false, "prints statistics to the screen") 61 | flag.BoolVar(&printHelp, "h", false, "Prints this help info and exits") 62 | flag.BoolVar(&printHelp, "help", false, "Prints this help info and exits") 63 | flag.Parse() 64 | println("MPG-Go") 65 | println("======") 66 | if videoPath == "" || printHelp { 67 | flag.PrintDefaults() 68 | return 69 | } 70 | 71 | g.player, err = mpg.NewPlayerFromFilename(videoPath) 72 | if err != nil { 73 | println("Error:", err.Error()) 74 | return 75 | } 76 | defer g.player.Close() 77 | 78 | // Setup and display generic stats 79 | fmt.Printf( 80 | "Create player successful\n"+ 81 | "\tDuration: %s\n\n", 82 | g.player.Duration().Round(time.Second/100), 83 | ) 84 | if g.loop { 85 | g.player.SetLoop(true) 86 | } 87 | 88 | ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled) 89 | 90 | // Setup and display video stats 91 | vStreams := g.player.NumVideoStreams() 92 | if g.player.HasVideo() { 93 | width, height := g.player.Width(), g.player.Height() 94 | framerate := g.player.FrameRate() 95 | fmt.Printf( 96 | "Video detected\n"+ 97 | "\tNumChannels: %d\n"+ 98 | "\tWidth: %d\n"+ 99 | "\tHeight: %d\n"+ 100 | "\tFrameRate: %00.2f\n\n", 101 | vStreams, width, height, framerate, 102 | ) 103 | ebiten.SetWindowSize(width, height) 104 | 105 | g.videoFrame = image.NewRGBA(image.Rectangle{ 106 | image.Point{}, 107 | image.Point{width, height}, 108 | }) 109 | 110 | // DrawRGBAPixels does not set alpha channels, so we set them here. 111 | mpg.SetAlpha(0xFF, g.videoFrame.Pix) 112 | 113 | g.videoImage = ebiten.NewImageFromImage(g.videoFrame) 114 | 115 | g.previewFrame = image.NewRGBA(image.Rectangle{ 116 | image.Point{}, 117 | image.Point{width, height}, 118 | }) 119 | // same for DrawFrameAsRGBAPixels. 120 | mpg.SetAlpha(0xFF, g.previewFrame.Pix) 121 | 122 | g.previewImage = ebiten.NewImageFromImage(g.previewFrame) 123 | g.previewPos = &ebiten.DrawImageOptions{} 124 | } else { 125 | fmt.Printf( 126 | "No video detected\n"+ 127 | "\tNumChannels: %d\n\n", 128 | vStreams, 129 | ) 130 | } 131 | 132 | // Setup and display Audio stats. 133 | aStreams := g.player.NumAudioStreams() 134 | if g.player.HasAudio() { 135 | samplerate := g.player.SampleRate() 136 | fmt.Printf( 137 | "Audio detected\n"+ 138 | "\tNumChannels: %d\n"+ 139 | "\tSampleRate: %d\n\n", 140 | aStreams, samplerate, 141 | ) 142 | g.ctx = audio.NewContext(samplerate) 143 | g.p, _ = g.ctx.NewPlayer(g.player) 144 | g.p.SetBufferSize(g.player.AudioLeadTime()) 145 | g.p.Play() 146 | } else { 147 | fmt.Printf( 148 | "No audio detected\n"+ 149 | "\tNumChannels: %d\n\n", 150 | aStreams, 151 | ) 152 | } 153 | // g.p.Clo 154 | 155 | fmt.Print( 156 | "Controls:\n" + 157 | "\t[space] pause/play stream\n" + 158 | "\t[esc] stop the stream and exits\n" + 159 | "\t[<-] seek back 15 sec\n" + 160 | "\t[->] seek forward 15 sec\n\n") 161 | 162 | // Start stream and runs ebiten. 163 | g.Play() 164 | if err := ebiten.RunGame(g); err != nil && err != done { 165 | panic(err.Error()) 166 | } else if err == done { 167 | fmt.Println("\nDone!") 168 | } 169 | } 170 | 171 | func (g *Game) Update() error { 172 | // Exit the player if the stream is finished or the escape key is pressed. 173 | if g.player.Finished() || inpututil.IsKeyJustReleased(ebiten.KeyEscape) { 174 | return done 175 | } 176 | 177 | // Space key to play or pause the stream. 178 | if inpututil.IsKeyJustReleased(ebiten.KeySpace) { 179 | g.TogglePlaying() 180 | } 181 | 182 | // seek 15 seconds forward and backward using arrow keys. 183 | if inpututil.IsKeyJustReleased(ebiten.KeyRight) { 184 | g.player.Seek(g.player.Time()+15*time.Second, true) 185 | } else if inpututil.IsKeyJustReleased(ebiten.KeyLeft) { 186 | g.player.Seek(g.player.Time()-15*time.Second, true) 187 | } 188 | 189 | // Process stream, progress bar, and allow scrubbing to specific periods of the stream. 190 | width, height := float64(g.player.Width()), float64(g.player.Height()) 191 | mouseX, mouseY := ebiten.CursorPosition() 192 | g.playheadColor = color.Alpha{0x10} 193 | if float64(mouseY) < height && float64(mouseY) > height-15 { 194 | g.playheadColor = color.RGBA{0xFF, 0x00, 0x00, 0xFF} 195 | if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { 196 | g.scrubbing = true 197 | g.Pause() 198 | } 199 | } 200 | if g.scrubbing { 201 | g.playheadPos = float64(mouseX) / width 202 | if mouseX != g.pmouseX { 203 | // If mouse moved, grab a preview frame at specific time and draw it above the playhead. 204 | ok := g.player.ReadRGBAAt(g.previewFrame.Pix, time.Duration(float64(g.player.Duration())*float64(mouseX)/width), false) 205 | if ok { 206 | g.previewImage.ReplacePixels(g.previewFrame.Pix) 207 | g.previewPos.GeoM.Reset() 208 | g.previewPos.GeoM.Scale(0.25, 0.25) 209 | tx, ty := float64(mouseX)-width/8, height/4*3-15 210 | tx = math.Min(math.Max(0, tx), width/4*3) 211 | g.previewPos.GeoM.Translate(tx, ty) 212 | } 213 | g.pmouseX = mouseX 214 | } 215 | if inpututil.IsMouseButtonJustReleased(ebiten.MouseButtonLeft) { 216 | // Scrub to the playhead time and resume playback 217 | g.player.Seek(time.Duration(float64(g.player.Duration())*g.playheadPos), true) 218 | g.Play() 219 | g.scrubbing = false 220 | } 221 | } else { 222 | g.playheadPos = g.player.Time().Seconds() / g.player.Duration().Seconds() 223 | if g.playing { 224 | // Process and decode stream and sets playhead. 225 | now := time.Now() 226 | g.player.Decode(now.Sub(g.ptime)) 227 | g.ptime = now 228 | } 229 | } 230 | 231 | // Render frame to image. 232 | if g.player.HasNewFrame() { 233 | g.player.ReadRGBA(g.videoFrame.Pix) 234 | g.videoImage.ReplacePixels(g.videoFrame.Pix) 235 | } 236 | 237 | fmt.Printf("Progress: %s / %s\t\t\r", 238 | g.player.Time().Round(time.Second), 239 | g.player.Duration().Round(time.Second), 240 | ) 241 | return nil 242 | } 243 | 244 | func (g *Game) Draw(screen *ebiten.Image) { 245 | // Draws video if it exists. 246 | if g.videoImage != nil { 247 | screen.DrawImage(g.videoImage, nil) 248 | if g.scrubbing && g.previewImage != nil { 249 | screen.DrawImage(g.previewImage, g.previewPos) 250 | } 251 | } else { 252 | screen.Clear() 253 | } 254 | 255 | // Prints some information about performance and progress. 256 | if g.debug { 257 | ebitenutil.DebugPrint(screen, 258 | fmt.Sprintf( 259 | "Debug Info\n"+ 260 | " FPS: %0.2f\n"+ 261 | " TPS: %0.2f\n"+ 262 | " Current Time: %s\n", 263 | ebiten.CurrentFPS(), 264 | ebiten.CurrentTPS(), 265 | g.player.Time().Round(time.Second/100), 266 | ), 267 | ) 268 | } 269 | 270 | // Draws playhead and preview image. 271 | width, height := float64(g.player.Width()), float64(g.player.Height()) 272 | ebitenutil.DrawRect(screen, 0, height-15, width*g.playheadPos, 15, g.playheadColor) 273 | 274 | } 275 | 276 | func (g *Game) Layout(width, height int) (int, int) { 277 | return g.player.Width(), g.player.Height() 278 | } 279 | 280 | var done = Done{} 281 | 282 | // Returned when Ebiten is finished. 283 | type Done struct{} 284 | 285 | func (Done) Error() string { return "Done" } 286 | 287 | // TogglePlaying toggles whether the stream is playing or pausing. 288 | func (g *Game) TogglePlaying() { 289 | if g.playing { 290 | g.Pause() 291 | } else { 292 | g.Play() 293 | } 294 | } 295 | 296 | // Play the stream. 297 | func (g *Game) Play() { 298 | if g.playing { 299 | return 300 | } 301 | g.playing = true 302 | g.ptime = time.Now() 303 | } 304 | 305 | // Pause the stream. 306 | func (g *Game) Pause() { 307 | if !g.playing { 308 | return 309 | } 310 | g.playing = false 311 | g.player.ClearAudioBuffer() 312 | } 313 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/crazyinfin8/mpg-go 2 | 3 | go 1.18 4 | 5 | require github.com/gotranspile/cxgo v0.3.4-0.20220531073423-dd978a7bfe2c 6 | 7 | require github.com/hajimehoshi/ebiten/v2 v2.3.3 8 | 9 | require ( 10 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220516021902-eb3e265c7661 // indirect 11 | github.com/gofrs/flock v0.8.1 // indirect 12 | github.com/hajimehoshi/oto/v2 v2.1.0 // indirect 13 | github.com/jezek/xgb v1.0.1 // indirect 14 | golang.org/x/exp/shiny v0.0.0-20220518171630-0b5c67f07fdf // indirect 15 | golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect 16 | golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd // indirect 17 | golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect 18 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect 19 | maze.io/x/math32 v0.0.0-20181106113604-c78ed91899f1 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | git.maze.io/go/math32 v0.0.0-20181106113604-c78ed91899f1 h1:VptAfeYGT/FPuzWFzyvne+vdXT881tTmEMhV+txQ+E0= 2 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 5 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220516021902-eb3e265c7661 h1:1bpooddSK2996NWM/1TW59cchQOm9MkoV9DkhSJH1BI= 6 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220516021902-eb3e265c7661/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 7 | github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= 8 | github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 9 | github.com/gotranspile/cxgo v0.3.4-0.20220531073423-dd978a7bfe2c h1:07Eow9kNfxr7PscdmA0jjR+G5P07+9M2rw3vBo8fpSA= 10 | github.com/gotranspile/cxgo v0.3.4-0.20220531073423-dd978a7bfe2c/go.mod h1:VfEaZkuU81OYM7zz9iqKFf3wSeeTT0QJpVpXob0iHoY= 11 | github.com/hajimehoshi/bitmapfont/v2 v2.2.0/go.mod h1:Llj2wTYXMuCTJEw2ATNIO6HbFPOoBYPs08qLdFAxOsQ= 12 | github.com/hajimehoshi/ebiten/v2 v2.3.3 h1:v72UzprVvWGE+HGcypkLI9Ikd237fqzpio5idPk9KNI= 13 | github.com/hajimehoshi/ebiten/v2 v2.3.3/go.mod h1:vxwpo0q0oSi1cIll0Q3Ui33TVZgeHuFVYzIRk7FwuVk= 14 | github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE= 15 | github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= 16 | github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= 17 | github.com/hajimehoshi/oto/v2 v2.1.0 h1:/h+UkbKzhD7xBHOQlWgKUplBPZ+J4DK3P2Y7g2UF1X4= 18 | github.com/hajimehoshi/oto/v2 v2.1.0/go.mod h1:9i0oYbpJ8BhVGkXDKdXKfFthX1JUNfXjeTp944W8TGM= 19 | github.com/jakecoffman/cp v1.1.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg= 20 | github.com/jezek/xgb v1.0.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= 21 | github.com/jezek/xgb v1.0.1 h1:YUGhxps0aR7J2Xplbs23OHnV1mWaxFVcOl9b+1RQkt8= 22 | github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= 23 | github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= 24 | github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ= 25 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 26 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 27 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 28 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 29 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 30 | github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= 31 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 32 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 33 | github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 34 | github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 35 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 36 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 37 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 38 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 39 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 40 | golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= 41 | golang.org/x/exp/shiny v0.0.0-20220518171630-0b5c67f07fdf h1:IbXVp9Gov7/6bw4sWq9M/u1cr+mr2NA8SJWvFCnu4is= 42 | golang.org/x/exp/shiny v0.0.0-20220518171630-0b5c67f07fdf/go.mod h1:VjAR7z0ngyATZTELrBSkxOOHhhlnVUxDye4mcjx5h/8= 43 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 44 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 45 | golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 46 | golang.org/x/image v0.0.0-20220321031419-a8550c1d254a/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 47 | golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 h1:LRtI4W37N+KFebI/qV0OFiLUv4GLOWeEW5hn/KEJvxE= 48 | golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 49 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 50 | golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 51 | golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd h1:x1GptNaTtxPAlTVIAJk61fuXg0y17h09DTxyb+VNC/k= 52 | golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= 53 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 54 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 55 | golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 56 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 57 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 58 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 59 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 60 | golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 61 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 62 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 63 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 64 | golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= 65 | golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 66 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 67 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 68 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 69 | golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 70 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 71 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 72 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 73 | golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 74 | golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 75 | golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 76 | golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 77 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= 78 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 79 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 80 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 81 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 82 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 83 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 85 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 86 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 87 | golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= 88 | golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= 89 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 90 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 91 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 92 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 93 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 94 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 95 | maze.io/x/math32 v0.0.0-20181106113604-c78ed91899f1 h1:SgIJGhlYkU+wmyP0xBEOdLVRIwVR4HSp/9kfv1BSvKQ= 96 | maze.io/x/math32 v0.0.0-20181106113604-c78ed91899f1/go.mod h1:OL5aVu+KUQ0mSadkiIseNiKIX6dJ2Ul1RlNWSMCP5y8= 97 | -------------------------------------------------------------------------------- /mpg.go: -------------------------------------------------------------------------------- 1 | package mpg 2 | 3 | //go:generate go run github.com/gotranspile/cxgo/cmd/cxgo 4 | 5 | import ( 6 | "bytes" 7 | "image" 8 | "image/color" 9 | "image/draw" 10 | "os" 11 | "time" 12 | "unsafe" 13 | 14 | "github.com/gotranspile/cxgo/runtime/stdio" 15 | ) 16 | 17 | // ExpectedHeader is returned by "NewPlayer" functions when a file could not be processed 18 | type ExpectedHeader struct{} 19 | 20 | func (err ExpectedHeader) Error() string { return "Unable to find header" } 21 | 22 | // Player processes and decodes video and audio in MPG format (MPEG1 video 23 | // encoding and MP2 audio encoding) 24 | type Player struct { 25 | plm *plm_t 26 | 27 | frame frame 28 | hasNewFrame bool 29 | 30 | audioBuffer *bytes.Buffer 31 | byteDepth int 32 | maxSampleFrames int 33 | } 34 | 35 | func newPlayer(p *plm_t) (*Player, error) { 36 | if plm_has_headers(p) != _true { 37 | plm_destroy(p) 38 | return nil, ExpectedHeader{} 39 | } 40 | plm := new(Player) 41 | plm.plm = p 42 | plm.audioBuffer = new(bytes.Buffer) 43 | plm.byteDepth = 2 44 | plm.SetAudioLeadTime(45 * time.Millisecond) 45 | plm_set_video_decode_callback(plm.plm, videoCallback, unsafe.Pointer(plm)) 46 | plm_set_audio_decode_callback(plm.plm, audioCallback, unsafe.Pointer(plm)) 47 | return plm, nil 48 | } 49 | 50 | // NewPlayerFromFile creates a new player from a given file. The file is not 51 | // closed when the player is closed. 52 | func NewPlayerFromFile(f *os.File) (*Player, error) { 53 | p := plm_create_with_file(stdio.OpenFrom(f), _false) 54 | return newPlayer(p) 55 | } 56 | 57 | // NewPlayerFromFile creates a new player from a given filename. 58 | func NewPlayerFromFilename(file string) (*Player, error) { 59 | f, err := os.Open(file) 60 | if err != nil { 61 | return nil, err 62 | } 63 | p := plm_create_with_file(stdio.OpenFrom(f), _true) 64 | return newPlayer(p) 65 | } 66 | 67 | // NewPlayerFromBytes creates a new player from a list of raw bytes. 68 | func NewPlayerFromBytes(data []byte) (*Player, error) { 69 | p := plm_create_with_memory(&data[0], uint64(len(data)), _false) 70 | return newPlayer(p) 71 | } 72 | 73 | // Close closes the internal player and discards data. 74 | func (plm *Player) Close() { 75 | plm.frame = frame{} 76 | plm.audioBuffer.Reset() 77 | plm_destroy(plm.plm) 78 | plm.plm = nil 79 | } 80 | 81 | // *** Video *** 82 | 83 | func videoCallback(p *plm_t, f *plm_frame_t, u unsafe.Pointer) { 84 | plm := (*Player)(u) 85 | plm.frame = frame{f} 86 | plm.hasNewFrame = true 87 | } 88 | 89 | // HasVideo returns true if this file contains video. 90 | func (plm *Player) HasVideo() bool { return plm_get_num_video_streams(plm.plm) > 0 } 91 | 92 | // NumVideoStreams returns the number of video channels present in the file. 93 | // (0-1) 94 | func (plm *Player) NumVideoStreams() int { return int(plm_get_num_video_streams(plm.plm)) } 95 | 96 | // SetVideoEnabled sets whether video should be decododed. 97 | func (plm *Player) SetVideoEnabled(enabled bool) { plm_set_video_enabled(plm.plm, boolToInt(enabled)) } 98 | 99 | // VideoEnabled returns true if decoding video is enabled. 100 | func (plm *Player) VideoEnabled() bool { return plm_get_video_enabled(plm.plm) == _true } 101 | 102 | // HasNewFrame returns true if a new frame has been decoded. Drawing the current 103 | // frame sets this to false 104 | func (plm *Player) HasNewFrame() bool { return plm.hasNewFrame } 105 | 106 | // FrameRate is the number of frames in a second. 107 | func (plm *Player) FrameRate() float64 { return plm_get_framerate(plm.plm) } 108 | 109 | // Width is the width of the video 110 | func (plm *Player) Width() int { return int(plm_get_width(plm.plm)) } 111 | 112 | // Height is the height of the video. 113 | func (plm *Player) Height() int { return int(plm_get_height(plm.plm)) } 114 | 115 | // *** Audio *** 116 | 117 | func audioCallback(p *plm_t, samples *plm_samples_t, u unsafe.Pointer) { 118 | plm := (*Player)(u) 119 | if l, max := plm.audioBuffer.Len(), plm.maxSampleFrames*plm.byteDepth; max > 0 && l > max*4 { 120 | l -= max 121 | var discard [16]byte 122 | for l > 16 { 123 | plm.audioBuffer.Read(discard[:]) 124 | l -= 16 125 | } 126 | plm.audioBuffer.Read(discard[:l]) 127 | } 128 | plm.audioBuffer.Grow(plm_audio_samples_per_frame * plm.byteDepth * 2) 129 | switch plm.byteDepth { 130 | case 1: 131 | for i := 0; i < len(samples.Interleaved); i++ { 132 | b := int8(samples.Interleaved[i] * 0x7F) 133 | plm.audioBuffer.WriteByte(byte(b)) 134 | } 135 | case 2: 136 | for i := 0; i < len(samples.Interleaved); i++ { 137 | b := int16(samples.Interleaved[i] * 0x7FFF) 138 | plm.audioBuffer.WriteByte(byte(b)) 139 | plm.audioBuffer.WriteByte(byte(b >> 8)) 140 | } 141 | case 4: 142 | for i := 0; i < len(samples.Interleaved); i++ { 143 | b := int32(samples.Interleaved[i] * 0x7FFFFFFF) 144 | plm.audioBuffer.WriteByte(byte(b)) 145 | plm.audioBuffer.WriteByte(byte(b >> 8)) 146 | plm.audioBuffer.WriteByte(byte(b >> 16)) 147 | plm.audioBuffer.WriteByte(byte(b >> 24)) 148 | } 149 | } 150 | } 151 | 152 | // HasAudio returns true if this file contains audio. 153 | func (plm *Player) HasAudio() bool { return plm_get_num_audio_streams(plm.plm) > 0 } 154 | 155 | // NumAudioStreams returns the number of audio channels that are present in the 156 | // file. (0-4) 157 | func (plm *Player) NumAudioStreams() int { return int(plm_get_num_audio_streams(plm.plm)) } 158 | 159 | // SetAudioEnabled sets whether audio should be decoded. 160 | func (plm *Player) SetAudioEnabled(enabled bool) { plm_set_audio_enabled(plm.plm, boolToInt(enabled)) } 161 | 162 | //AudioEnabled returns true if decoding audio is enabled. 163 | func (plm *Player) AudioEnabled() bool { return plm_get_audio_enabled(plm.plm) == _true } 164 | 165 | // HasNewAudio returns true if the audio buffer still contains unread data. 166 | func (plm *Player) HasNewAudio() bool { return plm.audioBuffer.Len() > 0 } 167 | 168 | // ClearAudioBuffer clears the audio buffer. 169 | func (plm *Player) ClearAudioBuffer() { plm.audioBuffer.Reset() } 170 | 171 | // SampleRate is how many samples per second in the audio stream. 172 | func (plm *Player) SampleRate() int { return int(plm_get_samplerate(plm.plm)) } 173 | 174 | // SetAudioLeadTime sets how long the audio is decoded in advance or behind the 175 | // video decode time. this is typically set to the duration of the buffer of 176 | // your audio API. 177 | func (plm *Player) SetAudioLeadTime(time time.Duration) { 178 | plm.maxSampleFrames = int(time.Seconds() * float64(plm.SampleRate()) * 1.2) 179 | plm_set_audio_lead_time(plm.plm, time.Seconds()) 180 | } 181 | 182 | // AudioLeadTime is how long the audio is decoded in advance or behind the video 183 | // decode time. 184 | func (plm *Player) AudioLeadTime() time.Duration { 185 | return floatToSecs(plm_get_audio_lead_time(plm.plm)) 186 | } 187 | 188 | // ByteDepth is how many bytes are in each. 189 | func (plm *Player) ByteDepth() int { return plm.byteDepth } 190 | 191 | // SetByteDepth sets how many bytes per sample audio is decoded as. Currently 192 | // the values 1 (8-bit), 2 (16-bit), and 4 (32-bit) are supported. 193 | func (plm *Player) SetByteDepth(depth int) { 194 | if depth == 1 || depth == 2 || depth == 4 { 195 | plm.audioBuffer.Reset() 196 | plm.byteDepth = depth 197 | } 198 | } 199 | 200 | // *** Both *** 201 | 202 | // Time is how far the video has progressed. 203 | func (plm *Player) Time() time.Duration { return floatToSecs(plm_get_time(plm.plm)) } 204 | 205 | // Duration is how long the entire video is. 206 | func (plm *Player) Duration() time.Duration { return floatToSecs(plm_get_duration(plm.plm)) } 207 | 208 | // Rewind moves to the beginning. 209 | func (plm *Player) Rewind() { plm_rewind(plm.plm) } 210 | 211 | // Loop returns true if the video was set to loop when finished. 212 | func (plm *Player) Loop() bool { return plm_get_loop(plm.plm) == _true } 213 | 214 | // SetLoop sets whether the video should loop when finished. 215 | func (plm *Player) SetLoop(set bool) { plm_set_loop(plm.plm, boolToInt(set)) } 216 | 217 | // Finished returns true when the video has ended. This is always false when 218 | // looping. 219 | func (plm *Player) Finished() bool { return plm_has_ended(plm.plm) == _true } 220 | 221 | // Decode processes the video accordingly to the duration "elapsed". 222 | func (plm *Player) Decode(elapsed time.Duration) { plm_decode(plm.plm, elapsed.Seconds()) } 223 | 224 | // Seek to the specified time. 225 | // 226 | // If "exact" is false, this will seek to the nearest intra frame. 227 | // If "exact" is true, this will seek to the exact time. this can be slower 228 | // as each frame since the last intra frame would need to be decoded. 229 | // 230 | // Seek returns true when successful. 231 | func (plm *Player) Seek(time time.Duration, exact bool) bool { 232 | return plm_seek(plm.plm, time.Seconds(), boolToInt(exact)) == _true 233 | } 234 | 235 | // Read consumes and reads data from the audio buffer. If the audio buffer does 236 | // not have any audio, it sends 0 to buf until it is full. 237 | // 238 | // This is intended to make it easy to create an Ebiten or Oto player straight 239 | // from this *Player 240 | func (plm *Player) Read(buf []byte) (n int, err error) { 241 | n, _ = plm.audioBuffer.Read(buf) 242 | if n == 0 { 243 | n = len(buf) 244 | for i := 0; i < n; i++ { 245 | buf[i] = 0x00 246 | } 247 | } 248 | return 249 | } 250 | 251 | // *** frame *** 252 | 253 | // frame makes it easier to use and draw "plm_frame_t" as an "image.Image" 254 | type frame struct { 255 | *plm_frame_t 256 | } 257 | 258 | func (frame frame) ColorModel() color.Model { return color.YCbCrModel } 259 | 260 | func (frame frame) Bounds() image.Rectangle { 261 | return image.Rectangle{ 262 | image.Point{}, 263 | image.Point{int(frame.plm_frame_t.Width), int(frame.plm_frame_t.Height)}, 264 | } 265 | } 266 | 267 | var ycbcrBlack = color.YCbCrModel.Convert(color.Black) 268 | 269 | func (frame frame) At(x, y int) color.Color { 270 | width, height := int(frame.plm_frame_t.Width), int(frame.plm_frame_t.Height) 271 | if x+y*width < width*height { 272 | yIndex := x + y*width 273 | cIndex := x/2 + (y/2)*(width/2) 274 | return color.YCbCr{ 275 | Y: index(frame.Y.Data, yIndex), 276 | Cr: index(frame.Cr.Data, cIndex), 277 | Cb: index(frame.Cb.Data, cIndex), 278 | } 279 | } 280 | return ycbcrBlack 281 | } 282 | 283 | // DrawTo draws the current frame to the image in "img". 284 | func (plm *Player) DrawTo(img draw.Image) { 285 | if plm.frame.plm_frame_t != nil { 286 | draw.Draw(img, plm.frame.Bounds(), plm.frame, image.Point{}, draw.Src) 287 | } 288 | plm.hasNewFrame = false 289 | } 290 | 291 | // ReadRGBA overwrites the passed byte array in "data" in RGBA format. 292 | // Intended for writing the current frame directly to "image.RGBA.Pix". 293 | // 294 | // Alpha channels remain unchanged. 295 | // 296 | // ReadRGBA panics if the size of data does not match the size of the 297 | // frame (width * height * 4). 298 | func (plm *Player) ReadRGBA(data []byte) { 299 | if plm.frame.plm_frame_t != nil { 300 | width, height := plm.Width(), plm.Height() 301 | if len(data) != width*height*4 { 302 | panic("data should be the same size as Player") 303 | } 304 | plm_frame_to_rgba(plm.frame.plm_frame_t, bytesToUintPtr(data), int64(width)*4) 305 | } 306 | plm.hasNewFrame = false 307 | } 308 | 309 | // DrawFrameAt seeks to the specified time and draws the current frame to the 310 | // image in "img". 311 | // 312 | // If "exact" is false, this will seek to the nearest intra frame. 313 | // If "exact" is true, this will seek to the exact time. this can be slower as 314 | // each frame since the last intra frame would need to be decoded. 315 | // 316 | // DrawFrameAt returns true when successful. 317 | func (plm *Player) DrawFrameAt(img draw.Image, elapsed time.Duration, exact bool) bool { 318 | f := plm_seek_frame(plm.plm, elapsed.Seconds(), boolToInt(exact)) 319 | if f == nil { 320 | return false 321 | } 322 | src := frame{f} 323 | draw.Draw(img, img.Bounds(), src, image.Point{}, draw.Src) 324 | return true 325 | } 326 | 327 | // ReadRGBAAt seeks to the specified time and overwrites the passed 328 | // byte array in "data" in RGBA format. Intended mainly for writing the current 329 | // frame directly to "image.RGBA.Pix". 330 | // 331 | // If "exact" is false, this will seek to the nearest intra frame. 332 | // If "exact" is true, this will seek to the exact time. this can be slower as 333 | // each frame since the last intra frame would need to be decoded. 334 | // 335 | // ReadRGBAAt returns true when successful. 336 | // 337 | // Alpha channels remain unchanged. 338 | // 339 | // ReadRGBAAt panics if the size of data does not match the size of the 340 | // frame (width * height * 4). 341 | func (plm *Player) ReadRGBAAt(data []byte, elapsed time.Duration, exact bool) bool { 342 | width, height := plm.Width(), plm.Height() 343 | if len(data) != width*height*4 { 344 | panic("image.RGBA should be the same size as Player") 345 | } 346 | f := plm_seek_frame(plm.plm, elapsed.Seconds(), boolToInt(exact)) 347 | if f == nil { 348 | return false 349 | } 350 | plm_frame_to_rgba(f, bytesToUintPtr(data), int64(width*4)) 351 | return true 352 | } 353 | -------------------------------------------------------------------------------- /pl_mpeg.go: -------------------------------------------------------------------------------- 1 | // Code generated by go generate; DO NOT EDIT. 2 | 3 | // PL_MPEG Copywrite Dominic Szablewski 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | // this software and associated documentation files(the "Software"), to deal in 7 | // the Software without restriction, including without limitation the rights to 8 | // use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies 9 | // of the Software, and to permit persons to whom the Software is furnished to do 10 | // so, subject to the following conditions : 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | package mpg 22 | 23 | import ( 24 | "github.com/gotranspile/cxgo/runtime/cmath" 25 | "github.com/gotranspile/cxgo/runtime/libc" 26 | "github.com/gotranspile/cxgo/runtime/stdio" 27 | "math" 28 | "unsafe" 29 | ) 30 | 31 | const plm_packet_invalid_ts1 = -1 32 | const plm_audio_samples_per_frame = 1152 33 | const plm_buffer_default_size = 0x20000 34 | const _true = 1 35 | const _false = 0 36 | 37 | type plm_t struct { 38 | Demux *plm_demux_t 39 | Time float64 40 | Has_ended int64 41 | Loop int64 42 | Has_decoders int64 43 | Video_enabled int64 44 | Video_packet_type int64 45 | Video_buffer *plm_buffer_t 46 | Video_decoder *plm_video_t 47 | Audio_enabled int64 48 | Audio_stream_index int64 49 | Audio_packet_type int64 50 | Audio_lead_time float64 51 | Audio_buffer *plm_buffer_t 52 | Audio_decoder *plm_audio_t 53 | Video_decode_callback plm_video_decode_callback 54 | Video_decode_callback_user_data unsafe.Pointer 55 | Audio_decode_callback plm_audio_decode_callback 56 | Audio_decode_callback_user_data unsafe.Pointer 57 | } 58 | type plm_buffer_t struct { 59 | Bit_index uint64 60 | Capacity uint64 61 | Length uint64 62 | Total_size uint64 63 | Discard_read_bytes int64 64 | Has_ended int64 65 | Free_when_done int64 66 | Close_when_done int64 67 | Fh *stdio.File 68 | Load_callback plm_buffer_load_callback 69 | Load_callback_user_data unsafe.Pointer 70 | Bytes *uint8 71 | Mode plm_buffer_mode 72 | } 73 | type plm_demux_t struct { 74 | Buffer *plm_buffer_t 75 | Destroy_buffer_when_done int64 76 | System_clock_ref float64 77 | Last_file_size uint64 78 | Last_decoded_pts float64 79 | Start_time float64 80 | Duration float64 81 | Start_code int64 82 | Has_pack_header int64 83 | Has_system_header int64 84 | Has_headers int64 85 | Num_audio_streams int64 86 | Num_video_streams int64 87 | Current_packet plm_packet_t 88 | Next_packet plm_packet_t 89 | } 90 | type plm_video_t struct { 91 | Framerate float64 92 | Time float64 93 | Frames_decoded int64 94 | Width int64 95 | Height int64 96 | Mb_width int64 97 | Mb_height int64 98 | Mb_size int64 99 | Luma_width int64 100 | Luma_height int64 101 | Chroma_width int64 102 | Chroma_height int64 103 | Start_code int64 104 | Picture_type int64 105 | Motion_forward plm_video_motion_t 106 | Motion_backward plm_video_motion_t 107 | Has_sequence_header int64 108 | Quantizer_scale int64 109 | Slice_begin int64 110 | Macroblock_address int64 111 | Mb_row int64 112 | Mb_col int64 113 | Macroblock_type int64 114 | Macroblock_intra int64 115 | Dc_predictor [3]int64 116 | Buffer *plm_buffer_t 117 | Destroy_buffer_when_done int64 118 | Frame_current plm_frame_t 119 | Frame_forward plm_frame_t 120 | Frame_backward plm_frame_t 121 | Frames_data *uint8 122 | Block_data [64]int64 123 | Intra_quant_matrix [64]uint8 124 | Non_intra_quant_matrix [64]uint8 125 | Has_reference_frame int64 126 | Assume_no_b_frames int64 127 | } 128 | type plm_audio_t struct { 129 | Time float64 130 | Samples_decoded int64 131 | Samplerate_index int64 132 | Bitrate_index int64 133 | Version int64 134 | Layer int64 135 | Mode int64 136 | Bound int64 137 | V_pos int64 138 | Next_frame_data_size int64 139 | Has_header int64 140 | Buffer *plm_buffer_t 141 | Destroy_buffer_when_done int64 142 | Allocation [2][32]*plm_quantizer_spec_t 143 | Scale_factor_info [2][32]uint8 144 | Scale_factor [2][32][3]int64 145 | Sample [2][32][3]int64 146 | Samples plm_samples_t 147 | D [1024]float32 148 | V [2][1024]float32 149 | U [32]float32 150 | } 151 | type plm_packet_t struct { 152 | Type int64 153 | Pts float64 154 | Length uint64 155 | Data *uint8 156 | } 157 | type plm_plane_t struct { 158 | Width uint64 159 | Height uint64 160 | Data *uint8 161 | } 162 | type plm_frame_t struct { 163 | Time float64 164 | Width uint64 165 | Height uint64 166 | Y plm_plane_t 167 | Cr plm_plane_t 168 | Cb plm_plane_t 169 | } 170 | type plm_video_decode_callback func(self *plm_t, frame *plm_frame_t, user unsafe.Pointer) 171 | type plm_samples_t struct { 172 | Time float64 173 | Count uint64 174 | Interleaved [2304]float32 175 | } 176 | type plm_audio_decode_callback func(self *plm_t, samples *plm_samples_t, user unsafe.Pointer) 177 | type plm_buffer_load_callback func(self *plm_buffer_t, user unsafe.Pointer) 178 | 179 | var plm_demux_packet_private int64 = 189 180 | var plm_demux_packet_audio_1 int64 = 192 181 | var plm_demux_packet_audio_2 int64 = 193 182 | var plm_demux_packet_audio_3 int64 = 194 183 | var plm_demux_packet_audio_4 int64 = 194 184 | var plm_demux_packet_video_1 int64 = 224 185 | 186 | func plm_create_with_filename(filename *byte) *plm_t { 187 | var buffer *plm_buffer_t = plm_buffer_create_with_filename(filename) 188 | if buffer == nil { 189 | return nil 190 | } 191 | return plm_create_with_buffer(buffer, _true) 192 | } 193 | func plm_create_with_file(fh *stdio.File, close_when_done int64) *plm_t { 194 | var buffer *plm_buffer_t = plm_buffer_create_with_file(fh, close_when_done) 195 | return plm_create_with_buffer(buffer, _true) 196 | } 197 | func plm_create_with_memory(bytes *uint8, length uint64, free_when_done int64) *plm_t { 198 | var buffer *plm_buffer_t = plm_buffer_create_with_memory(bytes, length, free_when_done) 199 | return plm_create_with_buffer(buffer, _true) 200 | } 201 | func plm_create_with_buffer(buffer *plm_buffer_t, destroy_when_done int64) *plm_t { 202 | var self *plm_t = new(plm_t) 203 | *self = plm_t{} 204 | self.Demux = plm_demux_create(buffer, destroy_when_done) 205 | self.Video_enabled = _true 206 | self.Audio_enabled = _true 207 | plm_init_decoders(self) 208 | return self 209 | } 210 | func plm_init_decoders(self *plm_t) int64 { 211 | if self.Has_decoders != 0 { 212 | return _true 213 | } 214 | if plm_demux_has_headers(self.Demux) == 0 { 215 | return _false 216 | } 217 | if plm_demux_get_num_video_streams(self.Demux) > 0 { 218 | if self.Video_enabled != 0 { 219 | self.Video_packet_type = plm_demux_packet_video_1 220 | } 221 | self.Video_buffer = plm_buffer_create_with_capacity(128 * 1024) 222 | plm_buffer_set_load_callback(self.Video_buffer, func(self *plm_buffer_t, user unsafe.Pointer) { 223 | plm_read_video_packet(self, user) 224 | }, unsafe.Pointer(self)) 225 | } 226 | if plm_demux_get_num_audio_streams(self.Demux) > 0 { 227 | if self.Audio_enabled != 0 { 228 | self.Audio_packet_type = plm_demux_packet_audio_1 + self.Audio_stream_index 229 | } 230 | self.Audio_buffer = plm_buffer_create_with_capacity(128 * 1024) 231 | plm_buffer_set_load_callback(self.Audio_buffer, func(self *plm_buffer_t, user unsafe.Pointer) { 232 | plm_read_audio_packet(self, user) 233 | }, unsafe.Pointer(self)) 234 | } 235 | if self.Video_buffer != nil { 236 | self.Video_decoder = plm_video_create_with_buffer(self.Video_buffer, _true) 237 | } 238 | if self.Audio_buffer != nil { 239 | self.Audio_decoder = plm_audio_create_with_buffer(self.Audio_buffer, _true) 240 | } 241 | self.Has_decoders = _true 242 | return _true 243 | } 244 | func plm_destroy(self *plm_t) { 245 | if self.Video_decoder != nil { 246 | plm_video_destroy(self.Video_decoder) 247 | } 248 | if self.Audio_decoder != nil { 249 | plm_audio_destroy(self.Audio_decoder) 250 | } 251 | plm_demux_destroy(self.Demux) 252 | libc.Free(unsafe.Pointer(self)) 253 | } 254 | func plm_get_audio_enabled(self *plm_t) int64 { 255 | return self.Audio_enabled 256 | } 257 | func plm_has_headers(self *plm_t) int64 { 258 | if plm_demux_has_headers(self.Demux) == 0 { 259 | return _false 260 | } 261 | if plm_init_decoders(self) == 0 { 262 | return _false 263 | } 264 | if self.Video_decoder != nil && plm_video_has_header(self.Video_decoder) == 0 || self.Audio_decoder != nil && plm_audio_has_header(self.Audio_decoder) == 0 { 265 | return _false 266 | } 267 | return _true 268 | } 269 | func plm_set_audio_enabled(self *plm_t, enabled int64) { 270 | self.Audio_enabled = enabled 271 | if enabled == 0 { 272 | self.Audio_packet_type = 0 273 | return 274 | } 275 | if plm_init_decoders(self) != 0 && self.Audio_decoder != nil { 276 | self.Audio_packet_type = plm_demux_packet_audio_1 + self.Audio_stream_index 277 | } else { 278 | self.Audio_packet_type = 0 279 | } 280 | } 281 | func plm_set_audio_stream(self *plm_t, stream_index int64) { 282 | if stream_index < 0 || stream_index > 3 { 283 | return 284 | } 285 | self.Audio_stream_index = stream_index 286 | plm_set_audio_enabled(self, self.Audio_enabled) 287 | } 288 | func plm_get_video_enabled(self *plm_t) int64 { 289 | return self.Video_enabled 290 | } 291 | func plm_set_video_enabled(self *plm_t, enabled int64) { 292 | self.Video_enabled = enabled 293 | if enabled == 0 { 294 | self.Video_packet_type = 0 295 | return 296 | } 297 | if plm_init_decoders(self) != 0 && self.Video_decoder != nil { 298 | self.Video_packet_type = plm_demux_packet_video_1 299 | } else { 300 | self.Video_packet_type = 0 301 | } 302 | } 303 | func plm_get_num_video_streams(self *plm_t) int64 { 304 | return plm_demux_get_num_video_streams(self.Demux) 305 | } 306 | func plm_get_width(self *plm_t) int64 { 307 | if plm_init_decoders(self) != 0 && self.Video_decoder != nil { 308 | return plm_video_get_width(self.Video_decoder) 309 | } 310 | return 0 311 | } 312 | func plm_get_height(self *plm_t) int64 { 313 | if plm_init_decoders(self) != 0 && self.Video_decoder != nil { 314 | return plm_video_get_height(self.Video_decoder) 315 | } 316 | return 0 317 | } 318 | func plm_get_framerate(self *plm_t) float64 { 319 | if plm_init_decoders(self) != 0 && self.Video_decoder != nil { 320 | return plm_video_get_framerate(self.Video_decoder) 321 | } 322 | return 0 323 | } 324 | func plm_get_num_audio_streams(self *plm_t) int64 { 325 | return plm_demux_get_num_audio_streams(self.Demux) 326 | } 327 | func plm_get_samplerate(self *plm_t) int64 { 328 | if plm_init_decoders(self) != 0 && self.Audio_decoder != nil { 329 | return plm_audio_get_samplerate(self.Audio_decoder) 330 | } 331 | return 0 332 | } 333 | func plm_get_audio_lead_time(self *plm_t) float64 { 334 | return self.Audio_lead_time 335 | } 336 | func plm_set_audio_lead_time(self *plm_t, lead_time float64) { 337 | self.Audio_lead_time = lead_time 338 | } 339 | func plm_get_time(self *plm_t) float64 { 340 | return self.Time 341 | } 342 | func plm_get_duration(self *plm_t) float64 { 343 | return plm_demux_get_duration(self.Demux, plm_demux_packet_video_1) 344 | } 345 | func plm_rewind(self *plm_t) { 346 | if self.Video_decoder != nil { 347 | plm_video_rewind(self.Video_decoder) 348 | } 349 | if self.Audio_decoder != nil { 350 | plm_audio_rewind(self.Audio_decoder) 351 | } 352 | plm_demux_rewind(self.Demux) 353 | self.Time = 0 354 | } 355 | func plm_get_loop(self *plm_t) int64 { 356 | return self.Loop 357 | } 358 | func plm_set_loop(self *plm_t, loop int64) { 359 | self.Loop = loop 360 | } 361 | func plm_has_ended(self *plm_t) int64 { 362 | return self.Has_ended 363 | } 364 | func plm_set_video_decode_callback(self *plm_t, fp plm_video_decode_callback, user unsafe.Pointer) { 365 | self.Video_decode_callback = fp 366 | self.Video_decode_callback_user_data = user 367 | } 368 | func plm_set_audio_decode_callback(self *plm_t, fp plm_audio_decode_callback, user unsafe.Pointer) { 369 | self.Audio_decode_callback = fp 370 | self.Audio_decode_callback_user_data = user 371 | } 372 | func plm_decode(self *plm_t, tick float64) { 373 | if plm_init_decoders(self) == 0 { 374 | return 375 | } 376 | var decode_video int64 = int64(libc.BoolToInt(self.Video_decode_callback != nil && self.Video_packet_type != 0)) 377 | var decode_audio int64 = int64(libc.BoolToInt(self.Audio_decode_callback != nil && self.Audio_packet_type != 0)) 378 | if decode_video == 0 && decode_audio == 0 { 379 | return 380 | } 381 | var did_decode int64 = _false 382 | var decode_video_failed int64 = _false 383 | var decode_audio_failed int64 = _false 384 | var video_target_time float64 = self.Time + tick 385 | var audio_target_time float64 = self.Time + tick + self.Audio_lead_time 386 | for { 387 | did_decode = _false 388 | if decode_video != 0 && plm_video_get_time(self.Video_decoder) < video_target_time { 389 | var frame *plm_frame_t = plm_video_decode(self.Video_decoder) 390 | if frame != nil { 391 | self.Video_decode_callback(self, frame, self.Video_decode_callback_user_data) 392 | did_decode = _true 393 | } else { 394 | decode_video_failed = _true 395 | } 396 | } 397 | if decode_audio != 0 && plm_audio_get_time(self.Audio_decoder) < audio_target_time { 398 | var samples *plm_samples_t = plm_audio_decode(self.Audio_decoder) 399 | if samples != nil { 400 | self.Audio_decode_callback(self, samples, self.Audio_decode_callback_user_data) 401 | did_decode = _true 402 | } else { 403 | decode_audio_failed = _true 404 | } 405 | } 406 | if did_decode == 0 { 407 | break 408 | } 409 | } 410 | if (decode_video == 0 || decode_video_failed != 0) && (decode_audio == 0 || decode_audio_failed != 0) && plm_demux_has_ended(self.Demux) != 0 { 411 | plm_handle_end(self) 412 | return 413 | } 414 | self.Time += tick 415 | } 416 | func plm_decode_video(self *plm_t) *plm_frame_t { 417 | if plm_init_decoders(self) == 0 { 418 | return nil 419 | } 420 | if self.Video_packet_type == 0 { 421 | return nil 422 | } 423 | var frame *plm_frame_t = plm_video_decode(self.Video_decoder) 424 | if frame != nil { 425 | self.Time = frame.Time 426 | } else if plm_demux_has_ended(self.Demux) != 0 { 427 | plm_handle_end(self) 428 | } 429 | return frame 430 | } 431 | func plm_decode_audio(self *plm_t) *plm_samples_t { 432 | if plm_init_decoders(self) == 0 { 433 | return nil 434 | } 435 | if self.Audio_packet_type == 0 { 436 | return nil 437 | } 438 | var samples *plm_samples_t = plm_audio_decode(self.Audio_decoder) 439 | if samples != nil { 440 | self.Time = samples.Time 441 | } else if plm_demux_has_ended(self.Demux) != 0 { 442 | plm_handle_end(self) 443 | } 444 | return samples 445 | } 446 | func plm_handle_end(self *plm_t) { 447 | if self.Loop != 0 { 448 | plm_rewind(self) 449 | } else { 450 | self.Has_ended = _true 451 | } 452 | } 453 | func plm_read_video_packet(buffer *plm_buffer_t, user unsafe.Pointer) { 454 | _ = buffer 455 | var self *plm_t = (*plm_t)(user) 456 | plm_read_packets(self, self.Video_packet_type) 457 | } 458 | func plm_read_audio_packet(buffer *plm_buffer_t, user unsafe.Pointer) { 459 | _ = buffer 460 | var self *plm_t = (*plm_t)(user) 461 | plm_read_packets(self, self.Audio_packet_type) 462 | } 463 | func plm_read_packets(self *plm_t, requested_type int64) { 464 | var packet *plm_packet_t 465 | for (func() *plm_packet_t { 466 | packet = plm_demux_decode(self.Demux) 467 | return packet 468 | }()) != nil { 469 | if packet.Type == self.Video_packet_type { 470 | plm_buffer_write(self.Video_buffer, packet.Data, packet.Length) 471 | } else if packet.Type == self.Audio_packet_type { 472 | plm_buffer_write(self.Audio_buffer, packet.Data, packet.Length) 473 | } 474 | if packet.Type == requested_type { 475 | return 476 | } 477 | } 478 | if plm_demux_has_ended(self.Demux) != 0 { 479 | if self.Video_buffer != nil { 480 | plm_buffer_signal_end(self.Video_buffer) 481 | } 482 | if self.Audio_buffer != nil { 483 | plm_buffer_signal_end(self.Audio_buffer) 484 | } 485 | } 486 | } 487 | func plm_seek_frame(self *plm_t, time float64, seek_exact int64) *plm_frame_t { 488 | if plm_init_decoders(self) == 0 { 489 | return nil 490 | } 491 | if self.Video_packet_type == 0 { 492 | return nil 493 | } 494 | var type_ int64 = self.Video_packet_type 495 | var start_time float64 = plm_demux_get_start_time(self.Demux, type_) 496 | var duration float64 = plm_demux_get_duration(self.Demux, type_) 497 | if time < 0 { 498 | time = 0 499 | } else if time > duration { 500 | time = duration 501 | } 502 | var packet *plm_packet_t = plm_demux_seek(self.Demux, time, type_, _true) 503 | if packet == nil { 504 | return nil 505 | } 506 | var previous_audio_packet_type int64 = self.Audio_packet_type 507 | self.Audio_packet_type = 0 508 | plm_video_rewind(self.Video_decoder) 509 | plm_video_set_time(self.Video_decoder, packet.Pts-start_time) 510 | plm_buffer_write(self.Video_buffer, packet.Data, packet.Length) 511 | var frame *plm_frame_t = plm_video_decode(self.Video_decoder) 512 | if seek_exact != 0 { 513 | for frame != nil && frame.Time < time { 514 | frame = plm_video_decode(self.Video_decoder) 515 | } 516 | } 517 | self.Audio_packet_type = previous_audio_packet_type 518 | if frame != nil { 519 | self.Time = frame.Time 520 | } 521 | self.Has_ended = _false 522 | return frame 523 | } 524 | func plm_seek(self *plm_t, time float64, seek_exact int64) int64 { 525 | var frame *plm_frame_t = plm_seek_frame(self, time, seek_exact) 526 | if frame == nil { 527 | return _false 528 | } 529 | if self.Video_decode_callback != nil { 530 | self.Video_decode_callback(self, frame, self.Video_decode_callback_user_data) 531 | } 532 | if self.Audio_packet_type == 0 { 533 | return _true 534 | } 535 | var start_time float64 = plm_demux_get_start_time(self.Demux, self.Video_packet_type) 536 | plm_audio_rewind(self.Audio_decoder) 537 | var packet *plm_packet_t = nil 538 | for (func() *plm_packet_t { 539 | packet = plm_demux_decode(self.Demux) 540 | return packet 541 | }()) != nil { 542 | if packet.Type == self.Video_packet_type { 543 | plm_buffer_write(self.Video_buffer, packet.Data, packet.Length) 544 | } else if packet.Type == self.Audio_packet_type && packet.Pts-start_time > self.Time { 545 | plm_audio_set_time(self.Audio_decoder, packet.Pts-start_time) 546 | plm_buffer_write(self.Audio_buffer, packet.Data, packet.Length) 547 | plm_decode(self, 0) 548 | break 549 | } 550 | } 551 | return _true 552 | } 553 | 554 | type plm_buffer_mode int64 555 | 556 | const ( 557 | plm_buffer_mode_file = plm_buffer_mode(iota) 558 | plm_buffer_mode_fixed_mem 559 | plm_buffer_mode_ring 560 | plm_buffer_mode_append 561 | ) 562 | 563 | type plm_vlc_t struct { 564 | Index int16 565 | Value int16 566 | } 567 | type plm_vlc_uint_t struct { 568 | Index int16 569 | Value uint16 570 | } 571 | 572 | func plm_buffer_create_with_filename(filename *byte) *plm_buffer_t { 573 | var fh *stdio.File = stdio.FOpen(libc.GoString(filename), "rb") 574 | if fh == nil { 575 | return nil 576 | } 577 | return plm_buffer_create_with_file(fh, _true) 578 | } 579 | func plm_buffer_create_with_file(fh *stdio.File, close_when_done int64) *plm_buffer_t { 580 | var self *plm_buffer_t = plm_buffer_create_with_capacity(128 * 1024) 581 | self.Fh = fh 582 | self.Close_when_done = close_when_done 583 | self.Mode = plm_buffer_mode(plm_buffer_mode_file) 584 | self.Discard_read_bytes = _true 585 | self.Fh.Seek(0, stdio.SEEK_END) 586 | self.Total_size = uint64(self.Fh.Tell()) 587 | self.Fh.Seek(0, stdio.SEEK_SET) 588 | plm_buffer_set_load_callback(self, func(self *plm_buffer_t, user unsafe.Pointer) { 589 | plm_buffer_load_file_callback(self, user) 590 | }, nil) 591 | return self 592 | } 593 | func plm_buffer_create_with_memory(bytes *uint8, length uint64, free_when_done int64) *plm_buffer_t { 594 | var self *plm_buffer_t = new(plm_buffer_t) 595 | *self = plm_buffer_t{} 596 | self.Capacity = length 597 | self.Length = length 598 | self.Total_size = length 599 | self.Free_when_done = free_when_done 600 | self.Bytes = bytes 601 | self.Mode = plm_buffer_mode(plm_buffer_mode_fixed_mem) 602 | self.Discard_read_bytes = _false 603 | return self 604 | } 605 | func plm_buffer_create_with_capacity(capacity uint64) *plm_buffer_t { 606 | var self *plm_buffer_t = new(plm_buffer_t) 607 | *self = plm_buffer_t{} 608 | self.Capacity = capacity 609 | self.Free_when_done = _true 610 | self.Bytes = (*uint8)(libc.Malloc(int(capacity))) 611 | self.Mode = plm_buffer_mode(plm_buffer_mode_ring) 612 | self.Discard_read_bytes = _true 613 | return self 614 | } 615 | func plm_buffer_create_for_appending(initial_capacity uint64) *plm_buffer_t { 616 | var self *plm_buffer_t = plm_buffer_create_with_capacity(initial_capacity) 617 | self.Mode = plm_buffer_mode(plm_buffer_mode_append) 618 | self.Discard_read_bytes = _false 619 | return self 620 | } 621 | func plm_buffer_destroy(self *plm_buffer_t) { 622 | if self.Fh != nil && self.Close_when_done != 0 { 623 | self.Fh.Close() 624 | } 625 | if self.Free_when_done != 0 { 626 | libc.Free(unsafe.Pointer(self.Bytes)) 627 | } 628 | libc.Free(unsafe.Pointer(self)) 629 | } 630 | func plm_buffer_get_size(self *plm_buffer_t) uint64 { 631 | if self.Mode == plm_buffer_mode(plm_buffer_mode_file) { 632 | return self.Total_size 633 | } 634 | return self.Length 635 | } 636 | func plm_buffer_get_remaining(self *plm_buffer_t) uint64 { 637 | return self.Length - (self.Bit_index >> 3) 638 | } 639 | func plm_buffer_write(self *plm_buffer_t, bytes *uint8, length uint64) uint64 { 640 | if self.Mode == plm_buffer_mode(plm_buffer_mode_fixed_mem) { 641 | return 0 642 | } 643 | if self.Discard_read_bytes != 0 { 644 | plm_buffer_discard_read_bytes(self) 645 | if self.Mode == plm_buffer_mode(plm_buffer_mode_ring) { 646 | self.Total_size = 0 647 | } 648 | } 649 | var bytes_available uint64 = self.Capacity - self.Length 650 | if bytes_available < length { 651 | var new_size uint64 = self.Capacity 652 | for { 653 | new_size *= 2 654 | if new_size-self.Length >= length { 655 | break 656 | } 657 | } 658 | self.Bytes = (*uint8)(libc.Realloc(unsafe.Pointer(self.Bytes), int(new_size))) 659 | self.Capacity = new_size 660 | } 661 | libc.MemCpy(unsafe.Add(unsafe.Pointer(self.Bytes), self.Length), unsafe.Pointer(bytes), int(length)) 662 | self.Length += length 663 | self.Has_ended = _false 664 | return length 665 | } 666 | func plm_buffer_signal_end(self *plm_buffer_t) { 667 | self.Total_size = self.Length 668 | } 669 | func plm_buffer_set_load_callback(self *plm_buffer_t, fp plm_buffer_load_callback, user unsafe.Pointer) { 670 | self.Load_callback = fp 671 | self.Load_callback_user_data = user 672 | } 673 | func plm_buffer_rewind(self *plm_buffer_t) { 674 | plm_buffer_seek(self, 0) 675 | } 676 | func plm_buffer_seek(self *plm_buffer_t, pos uint64) { 677 | self.Has_ended = _false 678 | if self.Mode == plm_buffer_mode(plm_buffer_mode_file) { 679 | self.Fh.Seek(int64(pos), stdio.SEEK_SET) 680 | self.Bit_index = 0 681 | self.Length = 0 682 | } else if self.Mode == plm_buffer_mode(plm_buffer_mode_ring) { 683 | if pos != 0 { 684 | return 685 | } 686 | self.Bit_index = 0 687 | self.Length = 0 688 | self.Total_size = 0 689 | } else if pos < self.Length { 690 | self.Bit_index = pos << 3 691 | } 692 | } 693 | func plm_buffer_tell(self *plm_buffer_t) uint64 { 694 | if self.Mode == plm_buffer_mode(plm_buffer_mode_file) { 695 | return uint64(self.Fh.Tell()) + (self.Bit_index >> 3) - self.Length 696 | } 697 | return self.Bit_index >> 3 698 | } 699 | func plm_buffer_discard_read_bytes(self *plm_buffer_t) { 700 | var byte_pos uint64 = self.Bit_index >> 3 701 | if byte_pos == self.Length { 702 | self.Bit_index = 0 703 | self.Length = 0 704 | } else if byte_pos > 0 { 705 | libc.MemMove(unsafe.Pointer(self.Bytes), unsafe.Add(unsafe.Pointer(self.Bytes), byte_pos), int(self.Length-byte_pos)) 706 | self.Bit_index -= byte_pos << 3 707 | self.Length -= byte_pos 708 | } 709 | } 710 | func plm_buffer_load_file_callback(self *plm_buffer_t, user unsafe.Pointer) { 711 | _ = user 712 | if self.Discard_read_bytes != 0 { 713 | plm_buffer_discard_read_bytes(self) 714 | } 715 | var bytes_available uint64 = self.Capacity - self.Length 716 | var bytes_read uint64 = uint64(self.Fh.ReadN((*byte)(unsafe.Add(unsafe.Pointer(self.Bytes), self.Length)), 1, int(bytes_available))) 717 | self.Length += bytes_read 718 | if bytes_read == 0 { 719 | self.Has_ended = _true 720 | } 721 | } 722 | func plm_buffer_has_ended(self *plm_buffer_t) int64 { 723 | return self.Has_ended 724 | } 725 | func plm_buffer_has(self *plm_buffer_t, count uint64) int64 { 726 | if ((self.Length << 3) - self.Bit_index) >= count { 727 | return _true 728 | } 729 | if self.Load_callback != nil { 730 | self.Load_callback(self, self.Load_callback_user_data) 731 | if ((self.Length << 3) - self.Bit_index) >= count { 732 | return _true 733 | } 734 | } 735 | if self.Total_size != 0 && self.Length == self.Total_size { 736 | self.Has_ended = _true 737 | } 738 | return _false 739 | } 740 | func plm_buffer_read(self *plm_buffer_t, count int64) int64 { 741 | if plm_buffer_has(self, uint64(count)) == 0 { 742 | return 0 743 | } 744 | var value int64 = 0 745 | for count != 0 { 746 | var ( 747 | current_byte int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Bytes), self.Bit_index>>3))) 748 | remaining int64 = int64(8 - (self.Bit_index & 7)) 749 | read int64 750 | ) 751 | if remaining < count { 752 | read = remaining 753 | } else { 754 | read = count 755 | } 756 | var shift int64 = remaining - read 757 | var mask int64 = (math.MaxUint8 >> (8 - read)) 758 | value = (value << read) | (current_byte&(mask<>shift 759 | self.Bit_index += uint64(read) 760 | count -= read 761 | } 762 | return value 763 | } 764 | func plm_buffer_align(self *plm_buffer_t) { 765 | self.Bit_index = ((self.Bit_index + 7) >> 3) << 3 766 | } 767 | func plm_buffer_skip(self *plm_buffer_t, count uint64) { 768 | if plm_buffer_has(self, count) != 0 { 769 | self.Bit_index += count 770 | } 771 | } 772 | func plm_buffer_skip_bytes(self *plm_buffer_t, v uint8) int64 { 773 | plm_buffer_align(self) 774 | var skipped int64 = 0 775 | for plm_buffer_has(self, 8) != 0 && int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Bytes), self.Bit_index>>3))) == int64(v) { 776 | self.Bit_index += 8 777 | skipped++ 778 | } 779 | return skipped 780 | } 781 | func plm_buffer_next_start_code(self *plm_buffer_t) int64 { 782 | plm_buffer_align(self) 783 | for plm_buffer_has(self, 5<<3) != 0 { 784 | var byte_index uint64 = self.Bit_index >> 3 785 | if int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Bytes), byte_index))) == 0 && int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Bytes), byte_index+1))) == 0 && int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Bytes), byte_index+2))) == 1 { 786 | self.Bit_index = (byte_index + 4) << 3 787 | return int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Bytes), byte_index+3))) 788 | } 789 | self.Bit_index += 8 790 | } 791 | return -1 792 | } 793 | func plm_buffer_find_start_code(self *plm_buffer_t, code int64) int64 { 794 | var current int64 = 0 795 | for _true != 0 { 796 | current = plm_buffer_next_start_code(self) 797 | if current == code || current == -1 { 798 | return current 799 | } 800 | } 801 | return -1 802 | } 803 | func plm_buffer_has_start_code(self *plm_buffer_t, code int64) int64 { 804 | var ( 805 | previous_bit_index uint64 = self.Bit_index 806 | previous_discard_read_bytes int64 = self.Discard_read_bytes 807 | ) 808 | self.Discard_read_bytes = _false 809 | var current int64 = plm_buffer_find_start_code(self, code) 810 | self.Bit_index = previous_bit_index 811 | self.Discard_read_bytes = previous_discard_read_bytes 812 | return current 813 | } 814 | func plm_buffer_peek_non_zero(self *plm_buffer_t, bit_count int64) int64 { 815 | if plm_buffer_has(self, uint64(bit_count)) == 0 { 816 | return _false 817 | } 818 | var val int64 = plm_buffer_read(self, bit_count) 819 | self.Bit_index -= uint64(bit_count) 820 | return int64(libc.BoolToInt(val != 0)) 821 | } 822 | func plm_buffer_read_vlc(self *plm_buffer_t, table *plm_vlc_t) int16 { 823 | var state plm_vlc_t = plm_vlc_t{} 824 | for { 825 | state = *(*plm_vlc_t)(unsafe.Add(unsafe.Pointer(table), unsafe.Sizeof(plm_vlc_t{})*uintptr(int64(state.Index)+plm_buffer_read(self, 1)))) 826 | if int64(state.Index) <= 0 { 827 | break 828 | } 829 | } 830 | return state.Value 831 | } 832 | func plm_buffer_read_vlc_uint(self *plm_buffer_t, table *plm_vlc_uint_t) uint16 { 833 | return uint16(plm_buffer_read_vlc(self, (*plm_vlc_t)(unsafe.Pointer(table)))) 834 | } 835 | 836 | var plm_start_pack int64 = 186 837 | var plm_start_end int64 = 185 838 | var plm_start_system int64 = 187 839 | 840 | func plm_demux_create(buffer *plm_buffer_t, destroy_when_done int64) *plm_demux_t { 841 | var self *plm_demux_t = new(plm_demux_t) 842 | *self = plm_demux_t{} 843 | self.Buffer = buffer 844 | self.Destroy_buffer_when_done = destroy_when_done 845 | self.Start_time = float64(-1) 846 | self.Duration = float64(-1) 847 | self.Start_code = -1 848 | plm_demux_has_headers(self) 849 | return self 850 | } 851 | func plm_demux_destroy(self *plm_demux_t) { 852 | if self.Destroy_buffer_when_done != 0 { 853 | plm_buffer_destroy(self.Buffer) 854 | } 855 | libc.Free(unsafe.Pointer(self)) 856 | } 857 | func plm_demux_has_headers(self *plm_demux_t) int64 { 858 | if self.Has_headers != 0 { 859 | return _true 860 | } 861 | if self.Has_pack_header == 0 { 862 | if self.Start_code != plm_start_pack && plm_buffer_find_start_code(self.Buffer, plm_start_pack) == -1 { 863 | return _false 864 | } 865 | self.Start_code = plm_start_pack 866 | if plm_buffer_has(self.Buffer, 64) == 0 { 867 | return _false 868 | } 869 | self.Start_code = -1 870 | if plm_buffer_read(self.Buffer, 4) != 2 { 871 | return _false 872 | } 873 | self.System_clock_ref = plm_demux_decode_time(self) 874 | plm_buffer_skip(self.Buffer, 1) 875 | plm_buffer_skip(self.Buffer, 22) 876 | plm_buffer_skip(self.Buffer, 1) 877 | self.Has_pack_header = _true 878 | } 879 | if self.Has_system_header == 0 { 880 | if self.Start_code != plm_start_system && plm_buffer_find_start_code(self.Buffer, plm_start_system) == -1 { 881 | return _false 882 | } 883 | self.Start_code = plm_start_system 884 | if plm_buffer_has(self.Buffer, 56) == 0 { 885 | return _false 886 | } 887 | self.Start_code = -1 888 | plm_buffer_skip(self.Buffer, 16) 889 | plm_buffer_skip(self.Buffer, 24) 890 | self.Num_audio_streams = plm_buffer_read(self.Buffer, 6) 891 | plm_buffer_skip(self.Buffer, 5) 892 | self.Num_video_streams = plm_buffer_read(self.Buffer, 5) 893 | self.Has_system_header = _true 894 | } 895 | self.Has_headers = _true 896 | return _true 897 | } 898 | func plm_demux_get_num_video_streams(self *plm_demux_t) int64 { 899 | if plm_demux_has_headers(self) != 0 { 900 | return self.Num_video_streams 901 | } 902 | return 0 903 | } 904 | func plm_demux_get_num_audio_streams(self *plm_demux_t) int64 { 905 | if plm_demux_has_headers(self) != 0 { 906 | return self.Num_audio_streams 907 | } 908 | return 0 909 | } 910 | func plm_demux_rewind(self *plm_demux_t) { 911 | plm_buffer_rewind(self.Buffer) 912 | self.Current_packet.Length = 0 913 | self.Next_packet.Length = 0 914 | self.Start_code = -1 915 | } 916 | func plm_demux_has_ended(self *plm_demux_t) int64 { 917 | return plm_buffer_has_ended(self.Buffer) 918 | } 919 | func plm_demux_buffer_seek(self *plm_demux_t, pos uint64) { 920 | plm_buffer_seek(self.Buffer, pos) 921 | self.Current_packet.Length = 0 922 | self.Next_packet.Length = 0 923 | self.Start_code = -1 924 | } 925 | func plm_demux_get_start_time(self *plm_demux_t, type_ int64) float64 { 926 | if self.Start_time != float64(-1) { 927 | return self.Start_time 928 | } 929 | var previous_pos int64 = int64(plm_buffer_tell(self.Buffer)) 930 | var previous_start_code int64 = self.Start_code 931 | plm_demux_rewind(self) 932 | for { 933 | { 934 | var packet *plm_packet_t = plm_demux_decode(self) 935 | if packet == nil { 936 | break 937 | } 938 | if packet.Type == type_ { 939 | self.Start_time = packet.Pts 940 | } 941 | } 942 | if self.Start_time != float64(-1) { 943 | break 944 | } 945 | } 946 | plm_demux_buffer_seek(self, uint64(previous_pos)) 947 | self.Start_code = previous_start_code 948 | return self.Start_time 949 | } 950 | func plm_demux_get_duration(self *plm_demux_t, type_ int64) float64 { 951 | var file_size uint64 = plm_buffer_get_size(self.Buffer) 952 | if self.Duration != float64(-1) && self.Last_file_size == file_size { 953 | return self.Duration 954 | } 955 | var previous_pos uint64 = plm_buffer_tell(self.Buffer) 956 | var previous_start_code int64 = self.Start_code 957 | var start_range int64 = 64 * 1024 958 | var max_range int64 = 4096 * 1024 959 | for range_ := int64(start_range); range_ <= max_range; range_ *= 2 { 960 | var seek_pos int64 = int64(file_size - uint64(range_)) 961 | if seek_pos < 0 { 962 | seek_pos = 0 963 | range_ = max_range 964 | } 965 | plm_demux_buffer_seek(self, uint64(seek_pos)) 966 | self.Current_packet.Length = 0 967 | var last_pts float64 = float64(-1) 968 | var packet *plm_packet_t = nil 969 | for (func() *plm_packet_t { 970 | packet = plm_demux_decode(self) 971 | return packet 972 | }()) != nil { 973 | if packet.Pts != float64(-1) && packet.Type == type_ { 974 | last_pts = packet.Pts 975 | } 976 | } 977 | if last_pts != float64(-1) { 978 | self.Duration = last_pts - plm_demux_get_start_time(self, type_) 979 | break 980 | } 981 | } 982 | plm_demux_buffer_seek(self, previous_pos) 983 | self.Start_code = previous_start_code 984 | self.Last_file_size = file_size 985 | return self.Duration 986 | } 987 | func plm_demux_seek(self *plm_demux_t, seek_time float64, type_ int64, force_intra int64) *plm_packet_t { 988 | if plm_demux_has_headers(self) == 0 { 989 | return nil 990 | } 991 | var duration float64 = plm_demux_get_duration(self, type_) 992 | var file_size int64 = int64(plm_buffer_get_size(self.Buffer)) 993 | var byterate int64 = int64(float64(file_size) / duration) 994 | var cur_time float64 = self.Last_decoded_pts 995 | var scan_span float64 = 1 996 | if seek_time > duration { 997 | seek_time = duration 998 | } else if seek_time < 0 { 999 | seek_time = 0 1000 | } 1001 | seek_time += self.Start_time 1002 | for retry := int64(0); retry < 32; retry++ { 1003 | var ( 1004 | found_packet_with_pts int64 = _false 1005 | found_packet_in_range int64 = _false 1006 | last_valid_packet_start int64 = -1 1007 | first_packet_time float64 = float64(-1) 1008 | cur_pos int64 = int64(plm_buffer_tell(self.Buffer)) 1009 | offset int64 = int64((seek_time - cur_time - scan_span) * float64(byterate)) 1010 | seek_pos int64 = cur_pos + offset 1011 | ) 1012 | if seek_pos < 0 { 1013 | seek_pos = 0 1014 | } else if seek_pos > file_size-256 { 1015 | seek_pos = file_size - 256 1016 | } 1017 | plm_demux_buffer_seek(self, uint64(seek_pos)) 1018 | for plm_buffer_find_start_code(self.Buffer, type_) != -1 { 1019 | var ( 1020 | packet_start int64 = int64(plm_buffer_tell(self.Buffer)) 1021 | packet *plm_packet_t = plm_demux_decode_packet(self, type_) 1022 | ) 1023 | if packet == nil || packet.Pts == float64(-1) { 1024 | continue 1025 | } 1026 | if packet.Pts > seek_time || packet.Pts < seek_time-scan_span { 1027 | found_packet_with_pts = _true 1028 | byterate = int64(float64(seek_pos-cur_pos) / (packet.Pts - cur_time)) 1029 | cur_time = packet.Pts 1030 | break 1031 | } 1032 | if found_packet_in_range == 0 { 1033 | found_packet_in_range = _true 1034 | first_packet_time = packet.Pts 1035 | } 1036 | if force_intra != 0 { 1037 | for i := uint64(0); i < packet.Length-6; i++ { 1038 | if int64(*(*uint8)(unsafe.Add(unsafe.Pointer(packet.Data), i))) == 0 && int64(*(*uint8)(unsafe.Add(unsafe.Pointer(packet.Data), i+1))) == 0 && int64(*(*uint8)(unsafe.Add(unsafe.Pointer(packet.Data), i+2))) == 1 && int64(*(*uint8)(unsafe.Add(unsafe.Pointer(packet.Data), i+3))) == 0 { 1039 | if (int64(*(*uint8)(unsafe.Add(unsafe.Pointer(packet.Data), i+5))) & 56) == 8 { 1040 | last_valid_packet_start = packet_start 1041 | } 1042 | break 1043 | } 1044 | } 1045 | } else { 1046 | last_valid_packet_start = packet_start 1047 | } 1048 | } 1049 | if last_valid_packet_start != -1 { 1050 | plm_demux_buffer_seek(self, uint64(last_valid_packet_start)) 1051 | return plm_demux_decode_packet(self, type_) 1052 | } else if found_packet_in_range != 0 { 1053 | scan_span *= 2 1054 | seek_time = first_packet_time 1055 | } else if found_packet_with_pts == 0 { 1056 | byterate = int64(float64(seek_pos-cur_pos) / (duration - cur_time)) 1057 | cur_time = duration 1058 | } 1059 | } 1060 | return nil 1061 | } 1062 | func plm_demux_decode(self *plm_demux_t) *plm_packet_t { 1063 | if plm_demux_has_headers(self) == 0 { 1064 | return nil 1065 | } 1066 | if self.Current_packet.Length != 0 { 1067 | var bits_till_next_packet uint64 = self.Current_packet.Length << 3 1068 | if plm_buffer_has(self.Buffer, bits_till_next_packet) == 0 { 1069 | return nil 1070 | } 1071 | plm_buffer_skip(self.Buffer, bits_till_next_packet) 1072 | self.Current_packet.Length = 0 1073 | } 1074 | if self.Next_packet.Length != 0 { 1075 | return plm_demux_get_packet(self) 1076 | } 1077 | if self.Start_code != -1 { 1078 | return plm_demux_decode_packet(self, self.Start_code) 1079 | } 1080 | for { 1081 | self.Start_code = plm_buffer_next_start_code(self.Buffer) 1082 | if self.Start_code == plm_demux_packet_video_1 || self.Start_code == plm_demux_packet_private || self.Start_code >= plm_demux_packet_audio_1 && self.Start_code <= plm_demux_packet_audio_4 { 1083 | return plm_demux_decode_packet(self, self.Start_code) 1084 | } 1085 | if self.Start_code == -1 { 1086 | break 1087 | } 1088 | } 1089 | return nil 1090 | } 1091 | func plm_demux_decode_time(self *plm_demux_t) float64 { 1092 | var clock int64 = plm_buffer_read(self.Buffer, 3) << 30 1093 | plm_buffer_skip(self.Buffer, 1) 1094 | clock |= plm_buffer_read(self.Buffer, 15) << 15 1095 | plm_buffer_skip(self.Buffer, 1) 1096 | clock |= plm_buffer_read(self.Buffer, 15) 1097 | plm_buffer_skip(self.Buffer, 1) 1098 | return float64(clock) / 90000.0 1099 | } 1100 | func plm_demux_decode_packet(self *plm_demux_t, type_ int64) *plm_packet_t { 1101 | if plm_buffer_has(self.Buffer, 16<<3) == 0 { 1102 | return nil 1103 | } 1104 | self.Start_code = -1 1105 | self.Next_packet.Type = type_ 1106 | self.Next_packet.Length = uint64(plm_buffer_read(self.Buffer, 16)) 1107 | self.Next_packet.Length -= uint64(plm_buffer_skip_bytes(self.Buffer, math.MaxUint8)) 1108 | if plm_buffer_read(self.Buffer, 2) == 1 { 1109 | plm_buffer_skip(self.Buffer, 16) 1110 | self.Next_packet.Length -= 2 1111 | } 1112 | var pts_dts_marker int64 = plm_buffer_read(self.Buffer, 2) 1113 | if pts_dts_marker == 3 { 1114 | self.Next_packet.Pts = plm_demux_decode_time(self) 1115 | self.Last_decoded_pts = self.Next_packet.Pts 1116 | plm_buffer_skip(self.Buffer, 40) 1117 | self.Next_packet.Length -= 10 1118 | } else if pts_dts_marker == 2 { 1119 | self.Next_packet.Pts = plm_demux_decode_time(self) 1120 | self.Last_decoded_pts = self.Next_packet.Pts 1121 | self.Next_packet.Length -= 5 1122 | } else if pts_dts_marker == 0 { 1123 | self.Next_packet.Pts = float64(-1) 1124 | plm_buffer_skip(self.Buffer, 4) 1125 | self.Next_packet.Length -= 1 1126 | } else { 1127 | return nil 1128 | } 1129 | return plm_demux_get_packet(self) 1130 | } 1131 | func plm_demux_get_packet(self *plm_demux_t) *plm_packet_t { 1132 | if plm_buffer_has(self.Buffer, self.Next_packet.Length<<3) == 0 { 1133 | return nil 1134 | } 1135 | self.Current_packet.Data = (*uint8)(unsafe.Add(unsafe.Pointer(self.Buffer.Bytes), self.Buffer.Bit_index>>3)) 1136 | self.Current_packet.Length = self.Next_packet.Length 1137 | self.Current_packet.Type = self.Next_packet.Type 1138 | self.Current_packet.Pts = self.Next_packet.Pts 1139 | self.Next_packet.Length = 0 1140 | return &self.Current_packet 1141 | } 1142 | 1143 | var plm_video_picture_type_intra int64 = 1 1144 | var plm_video_picture_type_predictive int64 = 2 1145 | var plm_video_picture_type_b int64 = 3 1146 | var plm_start_sequence int64 = 179 1147 | var plm_start_slice_first int64 = 1 1148 | var plm_start_slice_last int64 = 175 1149 | var plm_start_picture int64 = 0 1150 | var plm_start_extension int64 = 181 1151 | var plm_start_user_data int64 = 178 1152 | var plm_video_picture_rate [16]float64 = [16]float64{0.0, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0, 59.94, 60.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0} 1153 | var plm_video_zig_zag [64]uint8 = [64]uint8{0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63} 1154 | var plm_video_intra_quant_matrix [64]uint8 = [64]uint8{8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37, 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40, 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58, 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83} 1155 | var plm_video_non_intra_quant_matrix [64]uint8 = [64]uint8{16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16} 1156 | var plm_video_premultiplier_matrix [64]uint8 = [64]uint8{32, 44, 42, 38, 32, 25, 17, 9, 44, 62, 58, 52, 44, 35, 24, 12, 42, 58, 55, 49, 42, 33, 23, 12, 38, 52, 49, 44, 38, 30, 20, 10, 32, 44, 42, 38, 32, 25, 17, 9, 25, 35, 33, 30, 25, 20, 14, 7, 17, 24, 23, 20, 17, 14, 9, 5, 9, 12, 12, 10, 9, 7, 5, 2} 1157 | var plm_video_macroblock_address_increment [80]plm_vlc_t = [80]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 0, Value: 1}, {Index: 2 << 1, Value: 0}, {Index: 3 << 1, Value: 0}, {Index: 4 << 1, Value: 0}, {Index: 5 << 1, Value: 0}, {Index: 0, Value: 3}, {Index: 0, Value: 2}, {Index: 6 << 1, Value: 0}, {Index: 7 << 1, Value: 0}, {Index: 0, Value: 5}, {Index: 0, Value: 4}, {Index: 8 << 1, Value: 0}, {Index: 9 << 1, Value: 0}, {Index: 0, Value: 7}, {Index: 0, Value: 6}, {Index: 10 << 1, Value: 0}, {Index: 11 << 1, Value: 0}, {Index: 12 << 1, Value: 0}, {Index: 13 << 1, Value: 0}, {Index: 14 << 1, Value: 0}, {Index: 15 << 1, Value: 0}, {Index: 16 << 1, Value: 0}, {Index: 17 << 1, Value: 0}, {Index: 18 << 1, Value: 0}, {Index: 19 << 1, Value: 0}, {Index: 0, Value: 9}, {Index: 0, Value: 8}, {Index: -1, Value: 0}, {Index: 20 << 1, Value: 0}, {Index: -1, Value: 0}, {Index: 21 << 1, Value: 0}, {Index: 22 << 1, Value: 0}, {Index: 23 << 1, Value: 0}, {Index: 0, Value: 15}, {Index: 0, Value: 14}, {Index: 0, Value: 13}, {Index: 0, Value: 12}, {Index: 0, Value: 11}, {Index: 0, Value: 10}, {Index: 24 << 1, Value: 0}, {Index: 25 << 1, Value: 0}, {Index: 26 << 1, Value: 0}, {Index: 27 << 1, Value: 0}, {Index: 28 << 1, Value: 0}, {Index: 29 << 1, Value: 0}, {Index: 30 << 1, Value: 0}, {Index: 31 << 1, Value: 0}, {Index: 32 << 1, Value: 0}, {Index: -1, Value: 0}, {Index: -1, Value: 0}, {Index: 33 << 1, Value: 0}, {Index: 34 << 1, Value: 0}, {Index: 35 << 1, Value: 0}, {Index: 36 << 1, Value: 0}, {Index: 37 << 1, Value: 0}, {Index: 38 << 1, Value: 0}, {Index: 39 << 1, Value: 0}, {Index: 0, Value: 21}, {Index: 0, Value: 20}, {Index: 0, Value: 19}, {Index: 0, Value: 18}, {Index: 0, Value: 17}, {Index: 0, Value: 16}, {Index: 0, Value: 35}, {Index: -1, Value: 0}, {Index: -1, Value: 0}, {Index: 0, Value: 34}, {Index: 0, Value: 33}, {Index: 0, Value: 32}, {Index: 0, Value: 31}, {Index: 0, Value: 30}, {Index: 0, Value: 29}, {Index: 0, Value: 28}, {Index: 0, Value: 27}, {Index: 0, Value: 26}, {Index: 0, Value: 25}, {Index: 0, Value: 24}, {Index: 0, Value: 23}, {Index: 0, Value: 22}} 1158 | var plm_video_macroblock_type_intra [4]plm_vlc_t = [4]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 0, Value: 1}, {Index: -1, Value: 0}, {Index: 0, Value: 17}} 1159 | var plm_video_macroblock_type_predictive [14]plm_vlc_t = [14]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 0, Value: 10}, {Index: 2 << 1, Value: 0}, {Index: 0, Value: 2}, {Index: 3 << 1, Value: 0}, {Index: 0, Value: 8}, {Index: 4 << 1, Value: 0}, {Index: 5 << 1, Value: 0}, {Index: 6 << 1, Value: 0}, {Index: 0, Value: 18}, {Index: 0, Value: 26}, {Index: 0, Value: 1}, {Index: -1, Value: 0}, {Index: 0, Value: 17}} 1160 | var plm_video_macroblock_type_b [22]plm_vlc_t = [22]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 2 << 1, Value: 0}, {Index: 3 << 1, Value: 0}, {Index: 4 << 1, Value: 0}, {Index: 0, Value: 12}, {Index: 0, Value: 14}, {Index: 5 << 1, Value: 0}, {Index: 6 << 1, Value: 0}, {Index: 0, Value: 4}, {Index: 0, Value: 6}, {Index: 7 << 1, Value: 0}, {Index: 8 << 1, Value: 0}, {Index: 0, Value: 8}, {Index: 0, Value: 10}, {Index: 9 << 1, Value: 0}, {Index: 10 << 1, Value: 0}, {Index: 0, Value: 30}, {Index: 0, Value: 1}, {Index: -1, Value: 0}, {Index: 0, Value: 17}, {Index: 0, Value: 22}, {Index: 0, Value: 26}} 1161 | var plm_video_macroblock_type [4]*plm_vlc_t = [4]*plm_vlc_t{nil, &plm_video_macroblock_type_intra[0], &plm_video_macroblock_type_predictive[0], &plm_video_macroblock_type_b[0]} 1162 | var plm_video_code_block_pattern [126]plm_vlc_t = [126]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 2 << 1, Value: 0}, {Index: 3 << 1, Value: 0}, {Index: 4 << 1, Value: 0}, {Index: 5 << 1, Value: 0}, {Index: 6 << 1, Value: 0}, {Index: 7 << 1, Value: 0}, {Index: 8 << 1, Value: 0}, {Index: 9 << 1, Value: 0}, {Index: 10 << 1, Value: 0}, {Index: 11 << 1, Value: 0}, {Index: 12 << 1, Value: 0}, {Index: 13 << 1, Value: 0}, {Index: 0, Value: 60}, {Index: 14 << 1, Value: 0}, {Index: 15 << 1, Value: 0}, {Index: 16 << 1, Value: 0}, {Index: 17 << 1, Value: 0}, {Index: 18 << 1, Value: 0}, {Index: 19 << 1, Value: 0}, {Index: 20 << 1, Value: 0}, {Index: 21 << 1, Value: 0}, {Index: 22 << 1, Value: 0}, {Index: 23 << 1, Value: 0}, {Index: 0, Value: 32}, {Index: 0, Value: 16}, {Index: 0, Value: 8}, {Index: 0, Value: 4}, {Index: 24 << 1, Value: 0}, {Index: 25 << 1, Value: 0}, {Index: 26 << 1, Value: 0}, {Index: 27 << 1, Value: 0}, {Index: 28 << 1, Value: 0}, {Index: 29 << 1, Value: 0}, {Index: 30 << 1, Value: 0}, {Index: 31 << 1, Value: 0}, {Index: 0, Value: 62}, {Index: 0, Value: 2}, {Index: 0, Value: 61}, {Index: 0, Value: 1}, {Index: 0, Value: 56}, {Index: 0, Value: 52}, {Index: 0, Value: 44}, {Index: 0, Value: 28}, {Index: 0, Value: 40}, {Index: 0, Value: 20}, {Index: 0, Value: 48}, {Index: 0, Value: 12}, {Index: 32 << 1, Value: 0}, {Index: 33 << 1, Value: 0}, {Index: 34 << 1, Value: 0}, {Index: 35 << 1, Value: 0}, {Index: 36 << 1, Value: 0}, {Index: 37 << 1, Value: 0}, {Index: 38 << 1, Value: 0}, {Index: 39 << 1, Value: 0}, {Index: 40 << 1, Value: 0}, {Index: 41 << 1, Value: 0}, {Index: 42 << 1, Value: 0}, {Index: 43 << 1, Value: 0}, {Index: 0, Value: 63}, {Index: 0, Value: 3}, {Index: 0, Value: 36}, {Index: 0, Value: 24}, {Index: 44 << 1, Value: 0}, {Index: 45 << 1, Value: 0}, {Index: 46 << 1, Value: 0}, {Index: 47 << 1, Value: 0}, {Index: 48 << 1, Value: 0}, {Index: 49 << 1, Value: 0}, {Index: 50 << 1, Value: 0}, {Index: 51 << 1, Value: 0}, {Index: 52 << 1, Value: 0}, {Index: 53 << 1, Value: 0}, {Index: 54 << 1, Value: 0}, {Index: 55 << 1, Value: 0}, {Index: 56 << 1, Value: 0}, {Index: 57 << 1, Value: 0}, {Index: 58 << 1, Value: 0}, {Index: 59 << 1, Value: 0}, {Index: 0, Value: 34}, {Index: 0, Value: 18}, {Index: 0, Value: 10}, {Index: 0, Value: 6}, {Index: 0, Value: 33}, {Index: 0, Value: 17}, {Index: 0, Value: 9}, {Index: 0, Value: 5}, {Index: -1, Value: 0}, {Index: 60 << 1, Value: 0}, {Index: 61 << 1, Value: 0}, {Index: 62 << 1, Value: 0}, {Index: 0, Value: 58}, {Index: 0, Value: 54}, {Index: 0, Value: 46}, {Index: 0, Value: 30}, {Index: 0, Value: 57}, {Index: 0, Value: 53}, {Index: 0, Value: 45}, {Index: 0, Value: 29}, {Index: 0, Value: 38}, {Index: 0, Value: 26}, {Index: 0, Value: 37}, {Index: 0, Value: 25}, {Index: 0, Value: 43}, {Index: 0, Value: 23}, {Index: 0, Value: 51}, {Index: 0, Value: 15}, {Index: 0, Value: 42}, {Index: 0, Value: 22}, {Index: 0, Value: 50}, {Index: 0, Value: 14}, {Index: 0, Value: 41}, {Index: 0, Value: 21}, {Index: 0, Value: 49}, {Index: 0, Value: 13}, {Index: 0, Value: 35}, {Index: 0, Value: 19}, {Index: 0, Value: 11}, {Index: 0, Value: 7}, {Index: 0, Value: 39}, {Index: 0, Value: 27}, {Index: 0, Value: 59}, {Index: 0, Value: 55}, {Index: 0, Value: 47}, {Index: 0, Value: 31}} 1163 | var plm_video_motion [68]plm_vlc_t = [68]plm_vlc_t{{Index: 1 << 1, Value: 0}, {}, {Index: 2 << 1, Value: 0}, {Index: 3 << 1, Value: 0}, {Index: 4 << 1, Value: 0}, {Index: 5 << 1, Value: 0}, {Index: 0, Value: 1}, {Index: 0, Value: -1}, {Index: 6 << 1, Value: 0}, {Index: 7 << 1, Value: 0}, {Index: 0, Value: 2}, {Index: 0, Value: -2}, {Index: 8 << 1, Value: 0}, {Index: 9 << 1, Value: 0}, {Index: 0, Value: 3}, {Index: 0, Value: -3}, {Index: 10 << 1, Value: 0}, {Index: 11 << 1, Value: 0}, {Index: 12 << 1, Value: 0}, {Index: 13 << 1, Value: 0}, {Index: -1, Value: 0}, {Index: 14 << 1, Value: 0}, {Index: 15 << 1, Value: 0}, {Index: 16 << 1, Value: 0}, {Index: 17 << 1, Value: 0}, {Index: 18 << 1, Value: 0}, {Index: 0, Value: 4}, {Index: 0, Value: -4}, {Index: -1, Value: 0}, {Index: 19 << 1, Value: 0}, {Index: 20 << 1, Value: 0}, {Index: 21 << 1, Value: 0}, {Index: 0, Value: 7}, {Index: 0, Value: -7}, {Index: 0, Value: 6}, {Index: 0, Value: -6}, {Index: 0, Value: 5}, {Index: 0, Value: -5}, {Index: 22 << 1, Value: 0}, {Index: 23 << 1, Value: 0}, {Index: 24 << 1, Value: 0}, {Index: 25 << 1, Value: 0}, {Index: 26 << 1, Value: 0}, {Index: 27 << 1, Value: 0}, {Index: 28 << 1, Value: 0}, {Index: 29 << 1, Value: 0}, {Index: 30 << 1, Value: 0}, {Index: 31 << 1, Value: 0}, {Index: 32 << 1, Value: 0}, {Index: 33 << 1, Value: 0}, {Index: 0, Value: 10}, {Index: 0, Value: -10}, {Index: 0, Value: 9}, {Index: 0, Value: -9}, {Index: 0, Value: 8}, {Index: 0, Value: -8}, {Index: 0, Value: 16}, {Index: 0, Value: -16}, {Index: 0, Value: 15}, {Index: 0, Value: -15}, {Index: 0, Value: 14}, {Index: 0, Value: -14}, {Index: 0, Value: 13}, {Index: 0, Value: -13}, {Index: 0, Value: 12}, {Index: 0, Value: -12}, {Index: 0, Value: 11}, {Index: 0, Value: -11}} 1164 | var plm_video_dct_size_luminance [18]plm_vlc_t = [18]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 2 << 1, Value: 0}, {Index: 0, Value: 1}, {Index: 0, Value: 2}, {Index: 3 << 1, Value: 0}, {Index: 4 << 1, Value: 0}, {}, {Index: 0, Value: 3}, {Index: 0, Value: 4}, {Index: 5 << 1, Value: 0}, {Index: 0, Value: 5}, {Index: 6 << 1, Value: 0}, {Index: 0, Value: 6}, {Index: 7 << 1, Value: 0}, {Index: 0, Value: 7}, {Index: 8 << 1, Value: 0}, {Index: 0, Value: 8}, {Index: -1, Value: 0}} 1165 | var plm_video_dct_size_chrominance [18]plm_vlc_t = [18]plm_vlc_t{{Index: 1 << 1, Value: 0}, {Index: 2 << 1, Value: 0}, {}, {Index: 0, Value: 1}, {Index: 0, Value: 2}, {Index: 3 << 1, Value: 0}, {Index: 0, Value: 3}, {Index: 4 << 1, Value: 0}, {Index: 0, Value: 4}, {Index: 5 << 1, Value: 0}, {Index: 0, Value: 5}, {Index: 6 << 1, Value: 0}, {Index: 0, Value: 6}, {Index: 7 << 1, Value: 0}, {Index: 0, Value: 7}, {Index: 8 << 1, Value: 0}, {Index: 0, Value: 8}, {Index: -1, Value: 0}} 1166 | var plm_video_dct_size [3]*plm_vlc_t = [3]*plm_vlc_t{&plm_video_dct_size_luminance[0], &plm_video_dct_size_chrominance[0], &plm_video_dct_size_chrominance[0]} 1167 | var plm_video_dct_coeff [224]plm_vlc_uint_t = [224]plm_vlc_uint_t{{Index: 1 << 1, Value: 0}, {Index: 0, Value: 1}, {Index: 2 << 1, Value: 0}, {Index: 3 << 1, Value: 0}, {Index: 4 << 1, Value: 0}, {Index: 5 << 1, Value: 0}, {Index: 6 << 1, Value: 0}, {Index: 0, Value: 257}, {Index: 7 << 1, Value: 0}, {Index: 8 << 1, Value: 0}, {Index: 9 << 1, Value: 0}, {Index: 10 << 1, Value: 0}, {Index: 0, Value: 2}, {Index: 0, Value: 513}, {Index: 11 << 1, Value: 0}, {Index: 12 << 1, Value: 0}, {Index: 13 << 1, Value: 0}, {Index: 14 << 1, Value: 0}, {Index: 15 << 1, Value: 0}, {Index: 0, Value: 3}, {Index: 0, Value: 1025}, {Index: 0, Value: 769}, {Index: 16 << 1, Value: 0}, {Index: 0, Value: math.MaxUint16}, {Index: 17 << 1, Value: 0}, {Index: 18 << 1, Value: 0}, {Index: 0, Value: 1793}, {Index: 0, Value: 1537}, {Index: 0, Value: 258}, {Index: 0, Value: 1281}, {Index: 19 << 1, Value: 0}, {Index: 20 << 1, Value: 0}, {Index: 21 << 1, Value: 0}, {Index: 22 << 1, Value: 0}, {Index: 0, Value: 514}, {Index: 0, Value: 2305}, {Index: 0, Value: 4}, {Index: 0, Value: 2049}, {Index: 23 << 1, Value: 0}, {Index: 24 << 1, Value: 0}, {Index: 25 << 1, Value: 0}, {Index: 26 << 1, Value: 0}, {Index: 27 << 1, Value: 0}, {Index: 28 << 1, Value: 0}, {Index: 29 << 1, Value: 0}, {Index: 30 << 1, Value: 0}, {Index: 0, Value: 3329}, {Index: 0, Value: 6}, {Index: 0, Value: 3073}, {Index: 0, Value: 2817}, {Index: 0, Value: 770}, {Index: 0, Value: 259}, {Index: 0, Value: 5}, {Index: 0, Value: 2561}, {Index: 31 << 1, Value: 0}, {Index: 32 << 1, Value: 0}, {Index: 33 << 1, Value: 0}, {Index: 34 << 1, Value: 0}, {Index: 35 << 1, Value: 0}, {Index: 36 << 1, Value: 0}, {Index: 37 << 1, Value: 0}, {Index: 38 << 1, Value: 0}, {Index: 39 << 1, Value: 0}, {Index: 40 << 1, Value: 0}, {Index: 41 << 1, Value: 0}, {Index: 42 << 1, Value: 0}, {Index: 43 << 1, Value: 0}, {Index: 44 << 1, Value: 0}, {Index: 45 << 1, Value: 0}, {Index: 46 << 1, Value: 0}, {Index: 0, Value: 4097}, {Index: 0, Value: 1282}, {Index: 0, Value: 7}, {Index: 0, Value: 515}, {Index: 0, Value: 260}, {Index: 0, Value: 3841}, {Index: 0, Value: 3585}, {Index: 0, Value: 1026}, {Index: 47 << 1, Value: 0}, {Index: 48 << 1, Value: 0}, {Index: 49 << 1, Value: 0}, {Index: 50 << 1, Value: 0}, {Index: 51 << 1, Value: 0}, {Index: 52 << 1, Value: 0}, {Index: 53 << 1, Value: 0}, {Index: 54 << 1, Value: 0}, {Index: 55 << 1, Value: 0}, {Index: 56 << 1, Value: 0}, {Index: 57 << 1, Value: 0}, {Index: 58 << 1, Value: 0}, {Index: 59 << 1, Value: 0}, {Index: 60 << 1, Value: 0}, {Index: 61 << 1, Value: 0}, {Index: 62 << 1, Value: 0}, {Index: -1, Value: 0}, {Index: 63 << 1, Value: 0}, {Index: 64 << 1, Value: 0}, {Index: 65 << 1, Value: 0}, {Index: 66 << 1, Value: 0}, {Index: 67 << 1, Value: 0}, {Index: 68 << 1, Value: 0}, {Index: 69 << 1, Value: 0}, {Index: 70 << 1, Value: 0}, {Index: 71 << 1, Value: 0}, {Index: 72 << 1, Value: 0}, {Index: 73 << 1, Value: 0}, {Index: 74 << 1, Value: 0}, {Index: 75 << 1, Value: 0}, {Index: 76 << 1, Value: 0}, {Index: 77 << 1, Value: 0}, {Index: 0, Value: 11}, {Index: 0, Value: 2050}, {Index: 0, Value: 1027}, {Index: 0, Value: 10}, {Index: 0, Value: 516}, {Index: 0, Value: 1794}, {Index: 0, Value: 5377}, {Index: 0, Value: 5121}, {Index: 0, Value: 9}, {Index: 0, Value: 4865}, {Index: 0, Value: 4609}, {Index: 0, Value: 261}, {Index: 0, Value: 771}, {Index: 0, Value: 8}, {Index: 0, Value: 1538}, {Index: 0, Value: 4353}, {Index: 78 << 1, Value: 0}, {Index: 79 << 1, Value: 0}, {Index: 80 << 1, Value: 0}, {Index: 81 << 1, Value: 0}, {Index: 82 << 1, Value: 0}, {Index: 83 << 1, Value: 0}, {Index: 84 << 1, Value: 0}, {Index: 85 << 1, Value: 0}, {Index: 86 << 1, Value: 0}, {Index: 87 << 1, Value: 0}, {Index: 88 << 1, Value: 0}, {Index: 89 << 1, Value: 0}, {Index: 90 << 1, Value: 0}, {Index: 91 << 1, Value: 0}, {Index: 0, Value: 2562}, {Index: 0, Value: 2306}, {Index: 0, Value: 1283}, {Index: 0, Value: 772}, {Index: 0, Value: 517}, {Index: 0, Value: 263}, {Index: 0, Value: 262}, {Index: 0, Value: 15}, {Index: 0, Value: 14}, {Index: 0, Value: 13}, {Index: 0, Value: 12}, {Index: 0, Value: 6657}, {Index: 0, Value: 6401}, {Index: 0, Value: 6145}, {Index: 0, Value: 5889}, {Index: 0, Value: 5633}, {Index: 92 << 1, Value: 0}, {Index: 93 << 1, Value: 0}, {Index: 94 << 1, Value: 0}, {Index: 95 << 1, Value: 0}, {Index: 96 << 1, Value: 0}, {Index: 97 << 1, Value: 0}, {Index: 98 << 1, Value: 0}, {Index: 99 << 1, Value: 0}, {Index: 100 << 1, Value: 0}, {Index: 101 << 1, Value: 0}, {Index: 102 << 1, Value: 0}, {Index: 103 << 1, Value: 0}, {Index: 0, Value: 31}, {Index: 0, Value: 30}, {Index: 0, Value: 29}, {Index: 0, Value: 28}, {Index: 0, Value: 27}, {Index: 0, Value: 26}, {Index: 0, Value: 25}, {Index: 0, Value: 24}, {Index: 0, Value: 23}, {Index: 0, Value: 22}, {Index: 0, Value: 21}, {Index: 0, Value: 20}, {Index: 0, Value: 19}, {Index: 0, Value: 18}, {Index: 0, Value: 17}, {Index: 0, Value: 16}, {Index: 104 << 1, Value: 0}, {Index: 105 << 1, Value: 0}, {Index: 106 << 1, Value: 0}, {Index: 107 << 1, Value: 0}, {Index: 108 << 1, Value: 0}, {Index: 109 << 1, Value: 0}, {Index: 110 << 1, Value: 0}, {Index: 111 << 1, Value: 0}, {Index: 0, Value: 40}, {Index: 0, Value: 39}, {Index: 0, Value: 38}, {Index: 0, Value: 37}, {Index: 0, Value: 36}, {Index: 0, Value: 35}, {Index: 0, Value: 34}, {Index: 0, Value: 33}, {Index: 0, Value: 32}, {Index: 0, Value: 270}, {Index: 0, Value: 269}, {Index: 0, Value: 268}, {Index: 0, Value: 267}, {Index: 0, Value: 266}, {Index: 0, Value: 265}, {Index: 0, Value: 264}, {Index: 0, Value: 274}, {Index: 0, Value: 273}, {Index: 0, Value: 272}, {Index: 0, Value: 271}, {Index: 0, Value: 1539}, {Index: 0, Value: 4098}, {Index: 0, Value: 3842}, {Index: 0, Value: 3586}, {Index: 0, Value: 3330}, {Index: 0, Value: 3074}, {Index: 0, Value: 2818}, {Index: 0, Value: 7937}, {Index: 0, Value: 7681}, {Index: 0, Value: 7425}, {Index: 0, Value: 7169}, {Index: 0, Value: 6913}} 1168 | 1169 | type plm_video_motion_t struct { 1170 | Full_px int64 1171 | Is_set int64 1172 | R_size int64 1173 | H int64 1174 | V int64 1175 | } 1176 | 1177 | func plm_clamp(n int64) uint8 { 1178 | if n > math.MaxUint8 { 1179 | n = math.MaxUint8 1180 | } else if n < 0 { 1181 | n = 0 1182 | } 1183 | return uint8(int8(n)) 1184 | } 1185 | func plm_video_create_with_buffer(buffer *plm_buffer_t, destroy_when_done int64) *plm_video_t { 1186 | var self *plm_video_t = new(plm_video_t) 1187 | *self = plm_video_t{} 1188 | self.Buffer = buffer 1189 | self.Destroy_buffer_when_done = destroy_when_done 1190 | self.Start_code = plm_buffer_find_start_code(self.Buffer, plm_start_sequence) 1191 | if self.Start_code != -1 { 1192 | plm_video_decode_sequence_header(self) 1193 | } 1194 | return self 1195 | } 1196 | func plm_video_destroy(self *plm_video_t) { 1197 | if self.Destroy_buffer_when_done != 0 { 1198 | plm_buffer_destroy(self.Buffer) 1199 | } 1200 | if self.Has_sequence_header != 0 { 1201 | libc.Free(unsafe.Pointer(self.Frames_data)) 1202 | } 1203 | libc.Free(unsafe.Pointer(self)) 1204 | } 1205 | func plm_video_get_framerate(self *plm_video_t) float64 { 1206 | if plm_video_has_header(self) != 0 { 1207 | return self.Framerate 1208 | } 1209 | return 0 1210 | } 1211 | func plm_video_get_width(self *plm_video_t) int64 { 1212 | if plm_video_has_header(self) != 0 { 1213 | return self.Width 1214 | } 1215 | return 0 1216 | } 1217 | func plm_video_get_height(self *plm_video_t) int64 { 1218 | if plm_video_has_header(self) != 0 { 1219 | return self.Height 1220 | } 1221 | return 0 1222 | } 1223 | func plm_video_set_no_delay(self *plm_video_t, no_delay int64) { 1224 | self.Assume_no_b_frames = no_delay 1225 | } 1226 | func plm_video_get_time(self *plm_video_t) float64 { 1227 | return self.Time 1228 | } 1229 | func plm_video_set_time(self *plm_video_t, time float64) { 1230 | self.Frames_decoded = int64(self.Framerate * time) 1231 | self.Time = time 1232 | } 1233 | func plm_video_rewind(self *plm_video_t) { 1234 | plm_buffer_rewind(self.Buffer) 1235 | self.Time = 0 1236 | self.Frames_decoded = 0 1237 | self.Has_reference_frame = _false 1238 | self.Start_code = -1 1239 | } 1240 | func plm_video_has_ended(self *plm_video_t) int64 { 1241 | return plm_buffer_has_ended(self.Buffer) 1242 | } 1243 | func plm_video_decode(self *plm_video_t) *plm_frame_t { 1244 | if plm_video_has_header(self) == 0 { 1245 | return nil 1246 | } 1247 | var frame *plm_frame_t = nil 1248 | for { 1249 | if self.Start_code != plm_start_picture { 1250 | self.Start_code = plm_buffer_find_start_code(self.Buffer, plm_start_picture) 1251 | if self.Start_code == -1 { 1252 | if self.Has_reference_frame != 0 && self.Assume_no_b_frames == 0 && plm_buffer_has_ended(self.Buffer) != 0 && (self.Picture_type == plm_video_picture_type_intra || self.Picture_type == plm_video_picture_type_predictive) { 1253 | self.Has_reference_frame = _false 1254 | frame = &self.Frame_backward 1255 | break 1256 | } 1257 | return nil 1258 | } 1259 | } 1260 | if plm_buffer_has_start_code(self.Buffer, plm_start_picture) == -1 && plm_buffer_has_ended(self.Buffer) == 0 { 1261 | return nil 1262 | } 1263 | plm_buffer_discard_read_bytes(self.Buffer) 1264 | plm_video_decode_picture(self) 1265 | if self.Assume_no_b_frames != 0 { 1266 | frame = &self.Frame_backward 1267 | } else if self.Picture_type == plm_video_picture_type_b { 1268 | frame = &self.Frame_current 1269 | } else if self.Has_reference_frame != 0 { 1270 | frame = &self.Frame_forward 1271 | } else { 1272 | self.Has_reference_frame = _true 1273 | } 1274 | if frame != nil { 1275 | break 1276 | } 1277 | } 1278 | frame.Time = self.Time 1279 | self.Frames_decoded++ 1280 | self.Time = float64(self.Frames_decoded) / self.Framerate 1281 | return frame 1282 | } 1283 | func plm_video_has_header(self *plm_video_t) int64 { 1284 | if self.Has_sequence_header != 0 { 1285 | return _true 1286 | } 1287 | if self.Start_code != plm_start_sequence { 1288 | self.Start_code = plm_buffer_find_start_code(self.Buffer, plm_start_sequence) 1289 | } 1290 | if self.Start_code == -1 { 1291 | return _false 1292 | } 1293 | if plm_video_decode_sequence_header(self) == 0 { 1294 | return _false 1295 | } 1296 | return _true 1297 | } 1298 | func plm_video_decode_sequence_header(self *plm_video_t) int64 { 1299 | var max_header_size int64 = 64 + 2*64*8 1300 | if plm_buffer_has(self.Buffer, uint64(max_header_size)) == 0 { 1301 | return _false 1302 | } 1303 | self.Width = plm_buffer_read(self.Buffer, 12) 1304 | self.Height = plm_buffer_read(self.Buffer, 12) 1305 | if self.Width <= 0 || self.Height <= 0 { 1306 | return _false 1307 | } 1308 | plm_buffer_skip(self.Buffer, 4) 1309 | self.Framerate = plm_video_picture_rate[plm_buffer_read(self.Buffer, 4)] 1310 | plm_buffer_skip(self.Buffer, 18+1+10+1) 1311 | if plm_buffer_read(self.Buffer, 1) != 0 { 1312 | for i := int64(0); i < 64; i++ { 1313 | var idx int64 = int64(plm_video_zig_zag[i]) 1314 | self.Intra_quant_matrix[idx] = uint8(int8(plm_buffer_read(self.Buffer, 8))) 1315 | } 1316 | } else { 1317 | libc.MemCpy(unsafe.Pointer(&self.Intra_quant_matrix[0]), unsafe.Pointer(&plm_video_intra_quant_matrix[0]), 64) 1318 | } 1319 | if plm_buffer_read(self.Buffer, 1) != 0 { 1320 | for i := int64(0); i < 64; i++ { 1321 | var idx int64 = int64(plm_video_zig_zag[i]) 1322 | self.Non_intra_quant_matrix[idx] = uint8(int8(plm_buffer_read(self.Buffer, 8))) 1323 | } 1324 | } else { 1325 | libc.MemCpy(unsafe.Pointer(&self.Non_intra_quant_matrix[0]), unsafe.Pointer(&plm_video_non_intra_quant_matrix[0]), 64) 1326 | } 1327 | self.Mb_width = (self.Width + 15) >> 4 1328 | self.Mb_height = (self.Height + 15) >> 4 1329 | self.Mb_size = self.Mb_width * self.Mb_height 1330 | self.Luma_width = self.Mb_width << 4 1331 | self.Luma_height = self.Mb_height << 4 1332 | self.Chroma_width = self.Mb_width << 3 1333 | self.Chroma_height = self.Mb_height << 3 1334 | var luma_plane_size uint64 = uint64(self.Luma_width * self.Luma_height) 1335 | var chroma_plane_size uint64 = uint64(self.Chroma_width * self.Chroma_height) 1336 | var frame_data_size uint64 = (luma_plane_size + chroma_plane_size*2) 1337 | self.Frames_data = (*uint8)(libc.Malloc(int(frame_data_size * 3))) 1338 | plm_video_init_frame(self, &self.Frame_current, (*uint8)(unsafe.Add(unsafe.Pointer(self.Frames_data), frame_data_size*0))) 1339 | plm_video_init_frame(self, &self.Frame_forward, (*uint8)(unsafe.Add(unsafe.Pointer(self.Frames_data), frame_data_size*1))) 1340 | plm_video_init_frame(self, &self.Frame_backward, (*uint8)(unsafe.Add(unsafe.Pointer(self.Frames_data), frame_data_size*2))) 1341 | self.Has_sequence_header = _true 1342 | return _true 1343 | } 1344 | func plm_video_init_frame(self *plm_video_t, frame *plm_frame_t, base *uint8) { 1345 | var ( 1346 | luma_plane_size uint64 = uint64(self.Luma_width * self.Luma_height) 1347 | chroma_plane_size uint64 = uint64(self.Chroma_width * self.Chroma_height) 1348 | ) 1349 | frame.Width = uint64(self.Width) 1350 | frame.Height = uint64(self.Height) 1351 | frame.Y.Width = uint64(self.Luma_width) 1352 | frame.Y.Height = uint64(self.Luma_height) 1353 | frame.Y.Data = base 1354 | frame.Cr.Width = uint64(self.Chroma_width) 1355 | frame.Cr.Height = uint64(self.Chroma_height) 1356 | frame.Cr.Data = (*uint8)(unsafe.Add(unsafe.Pointer(base), luma_plane_size)) 1357 | frame.Cb.Width = uint64(self.Chroma_width) 1358 | frame.Cb.Height = uint64(self.Chroma_height) 1359 | frame.Cb.Data = (*uint8)(unsafe.Add(unsafe.Pointer((*uint8)(unsafe.Add(unsafe.Pointer(base), luma_plane_size))), chroma_plane_size)) 1360 | } 1361 | func plm_video_decode_picture(self *plm_video_t) { 1362 | plm_buffer_skip(self.Buffer, 10) 1363 | self.Picture_type = plm_buffer_read(self.Buffer, 3) 1364 | plm_buffer_skip(self.Buffer, 16) 1365 | if self.Picture_type <= 0 || self.Picture_type > plm_video_picture_type_b { 1366 | return 1367 | } 1368 | if self.Picture_type == plm_video_picture_type_predictive || self.Picture_type == plm_video_picture_type_b { 1369 | self.Motion_forward.Full_px = plm_buffer_read(self.Buffer, 1) 1370 | var f_code int64 = plm_buffer_read(self.Buffer, 3) 1371 | if f_code == 0 { 1372 | return 1373 | } 1374 | self.Motion_forward.R_size = f_code - 1 1375 | } 1376 | if self.Picture_type == plm_video_picture_type_b { 1377 | self.Motion_backward.Full_px = plm_buffer_read(self.Buffer, 1) 1378 | var f_code int64 = plm_buffer_read(self.Buffer, 3) 1379 | if f_code == 0 { 1380 | return 1381 | } 1382 | self.Motion_backward.R_size = f_code - 1 1383 | } 1384 | var frame_temp plm_frame_t = self.Frame_forward 1385 | if self.Picture_type == plm_video_picture_type_intra || self.Picture_type == plm_video_picture_type_predictive { 1386 | self.Frame_forward = self.Frame_backward 1387 | } 1388 | for { 1389 | self.Start_code = plm_buffer_next_start_code(self.Buffer) 1390 | if !(self.Start_code == plm_start_extension || self.Start_code == plm_start_user_data) { 1391 | break 1392 | } 1393 | } 1394 | for self.Start_code >= plm_start_slice_first && self.Start_code <= plm_start_slice_last { 1395 | plm_video_decode_slice(self, self.Start_code&math.MaxUint8) 1396 | if self.Macroblock_address >= self.Mb_size-2 { 1397 | break 1398 | } 1399 | self.Start_code = plm_buffer_next_start_code(self.Buffer) 1400 | } 1401 | if self.Picture_type == plm_video_picture_type_intra || self.Picture_type == plm_video_picture_type_predictive { 1402 | self.Frame_backward = self.Frame_current 1403 | self.Frame_current = frame_temp 1404 | } 1405 | } 1406 | func plm_video_decode_slice(self *plm_video_t, slice int64) { 1407 | self.Slice_begin = _true 1408 | self.Macroblock_address = (slice-1)*self.Mb_width - 1 1409 | self.Motion_backward.H = func() int64 { 1410 | p := &self.Motion_forward.H 1411 | self.Motion_forward.H = 0 1412 | return *p 1413 | }() 1414 | self.Motion_backward.V = func() int64 { 1415 | p := &self.Motion_forward.V 1416 | self.Motion_forward.V = 0 1417 | return *p 1418 | }() 1419 | self.Dc_predictor[0] = 128 1420 | self.Dc_predictor[1] = 128 1421 | self.Dc_predictor[2] = 128 1422 | self.Quantizer_scale = plm_buffer_read(self.Buffer, 5) 1423 | for plm_buffer_read(self.Buffer, 1) != 0 { 1424 | plm_buffer_skip(self.Buffer, 8) 1425 | } 1426 | for { 1427 | plm_video_decode_macroblock(self) 1428 | if !(self.Macroblock_address < self.Mb_size-1 && plm_buffer_peek_non_zero(self.Buffer, 23) != 0) { 1429 | break 1430 | } 1431 | } 1432 | } 1433 | func plm_video_decode_macroblock(self *plm_video_t) { 1434 | var ( 1435 | increment int64 = 0 1436 | t int64 = int64(plm_buffer_read_vlc(self.Buffer, &plm_video_macroblock_address_increment[0])) 1437 | ) 1438 | for t == 34 { 1439 | t = int64(plm_buffer_read_vlc(self.Buffer, &plm_video_macroblock_address_increment[0])) 1440 | } 1441 | for t == 35 { 1442 | increment += 33 1443 | t = int64(plm_buffer_read_vlc(self.Buffer, &plm_video_macroblock_address_increment[0])) 1444 | } 1445 | increment += t 1446 | if self.Slice_begin != 0 { 1447 | self.Slice_begin = _false 1448 | self.Macroblock_address += increment 1449 | } else { 1450 | if self.Macroblock_address+increment >= self.Mb_size { 1451 | return 1452 | } 1453 | if increment > 1 { 1454 | self.Dc_predictor[0] = 128 1455 | self.Dc_predictor[1] = 128 1456 | self.Dc_predictor[2] = 128 1457 | if self.Picture_type == plm_video_picture_type_predictive { 1458 | self.Motion_forward.H = 0 1459 | self.Motion_forward.V = 0 1460 | } 1461 | } 1462 | for increment > 1 { 1463 | self.Macroblock_address++ 1464 | self.Mb_row = self.Macroblock_address / self.Mb_width 1465 | self.Mb_col = self.Macroblock_address % self.Mb_width 1466 | plm_video_predict_macroblock(self) 1467 | increment-- 1468 | } 1469 | self.Macroblock_address++ 1470 | } 1471 | self.Mb_row = self.Macroblock_address / self.Mb_width 1472 | self.Mb_col = self.Macroblock_address % self.Mb_width 1473 | if self.Mb_col >= self.Mb_width || self.Mb_row >= self.Mb_height { 1474 | return 1475 | } 1476 | var table *plm_vlc_t = plm_video_macroblock_type[self.Picture_type] 1477 | self.Macroblock_type = int64(plm_buffer_read_vlc(self.Buffer, table)) 1478 | self.Macroblock_intra = self.Macroblock_type & 1 1479 | self.Motion_forward.Is_set = self.Macroblock_type & 8 1480 | self.Motion_backward.Is_set = self.Macroblock_type & 4 1481 | if (self.Macroblock_type & 16) != 0 { 1482 | self.Quantizer_scale = plm_buffer_read(self.Buffer, 5) 1483 | } 1484 | if self.Macroblock_intra != 0 { 1485 | self.Motion_backward.H = func() int64 { 1486 | p := &self.Motion_forward.H 1487 | self.Motion_forward.H = 0 1488 | return *p 1489 | }() 1490 | self.Motion_backward.V = func() int64 { 1491 | p := &self.Motion_forward.V 1492 | self.Motion_forward.V = 0 1493 | return *p 1494 | }() 1495 | } else { 1496 | self.Dc_predictor[0] = 128 1497 | self.Dc_predictor[1] = 128 1498 | self.Dc_predictor[2] = 128 1499 | plm_video_decode_motion_vectors(self) 1500 | plm_video_predict_macroblock(self) 1501 | } 1502 | var cbp int64 1503 | if (self.Macroblock_type & 2) != 0 { 1504 | cbp = int64(plm_buffer_read_vlc(self.Buffer, &plm_video_code_block_pattern[0])) 1505 | } else if self.Macroblock_intra != 0 { 1506 | cbp = 63 1507 | } else { 1508 | cbp = 0 1509 | } 1510 | for block, mask := int64(0), int64(32); block < 6; block++ { 1511 | if (cbp & mask) != 0 { 1512 | plm_video_decode_block(self, block) 1513 | } 1514 | mask >>= 1 1515 | } 1516 | } 1517 | func plm_video_decode_motion_vectors(self *plm_video_t) { 1518 | if self.Motion_forward.Is_set != 0 { 1519 | var r_size int64 = self.Motion_forward.R_size 1520 | self.Motion_forward.H = plm_video_decode_motion_vector(self, r_size, self.Motion_forward.H) 1521 | self.Motion_forward.V = plm_video_decode_motion_vector(self, r_size, self.Motion_forward.V) 1522 | } else if self.Picture_type == plm_video_picture_type_predictive { 1523 | self.Motion_forward.H = 0 1524 | self.Motion_forward.V = 0 1525 | } 1526 | if self.Motion_backward.Is_set != 0 { 1527 | var r_size int64 = self.Motion_backward.R_size 1528 | self.Motion_backward.H = plm_video_decode_motion_vector(self, r_size, self.Motion_backward.H) 1529 | self.Motion_backward.V = plm_video_decode_motion_vector(self, r_size, self.Motion_backward.V) 1530 | } 1531 | } 1532 | func plm_video_decode_motion_vector(self *plm_video_t, r_size int64, motion int64) int64 { 1533 | var ( 1534 | fscale int64 = 1 << r_size 1535 | m_code int64 = int64(plm_buffer_read_vlc(self.Buffer, &plm_video_motion[0])) 1536 | r int64 = 0 1537 | d int64 1538 | ) 1539 | if m_code != 0 && fscale != 1 { 1540 | r = plm_buffer_read(self.Buffer, r_size) 1541 | d = ((cmath.Abs(m_code) - 1) << r_size) + r + 1 1542 | if m_code < 0 { 1543 | d = -d 1544 | } 1545 | } else { 1546 | d = m_code 1547 | } 1548 | motion += d 1549 | if motion > (fscale<<4)-1 { 1550 | motion -= fscale << 5 1551 | } else if motion < ((-fscale) << 4) { 1552 | motion += fscale << 5 1553 | } 1554 | return motion 1555 | } 1556 | func plm_video_predict_macroblock(self *plm_video_t) { 1557 | var ( 1558 | fw_h int64 = self.Motion_forward.H 1559 | fw_v int64 = self.Motion_forward.V 1560 | ) 1561 | if self.Motion_forward.Full_px != 0 { 1562 | fw_h <<= 1 1563 | fw_v <<= 1 1564 | } 1565 | if self.Picture_type == plm_video_picture_type_b { 1566 | var ( 1567 | bw_h int64 = self.Motion_backward.H 1568 | bw_v int64 = self.Motion_backward.V 1569 | ) 1570 | if self.Motion_backward.Full_px != 0 { 1571 | bw_h <<= 1 1572 | bw_v <<= 1 1573 | } 1574 | if self.Motion_forward.Is_set != 0 { 1575 | plm_video_copy_macroblock(self, &self.Frame_forward, fw_h, fw_v) 1576 | if self.Motion_backward.Is_set != 0 { 1577 | plm_video_interpolate_macroblock(self, &self.Frame_backward, bw_h, bw_v) 1578 | } 1579 | } else { 1580 | plm_video_copy_macroblock(self, &self.Frame_backward, bw_h, bw_v) 1581 | } 1582 | } else { 1583 | plm_video_copy_macroblock(self, &self.Frame_forward, fw_h, fw_v) 1584 | } 1585 | } 1586 | func plm_video_copy_macroblock(self *plm_video_t, s *plm_frame_t, motion_h int64, motion_v int64) { 1587 | var d *plm_frame_t = &self.Frame_current 1588 | plm_video_process_macroblock(self, s.Y.Data, d.Y.Data, motion_h, motion_v, 16, _false) 1589 | plm_video_process_macroblock(self, s.Cr.Data, d.Cr.Data, motion_h/2, motion_v/2, 8, _false) 1590 | plm_video_process_macroblock(self, s.Cb.Data, d.Cb.Data, motion_h/2, motion_v/2, 8, _false) 1591 | } 1592 | func plm_video_interpolate_macroblock(self *plm_video_t, s *plm_frame_t, motion_h int64, motion_v int64) { 1593 | var d *plm_frame_t = &self.Frame_current 1594 | plm_video_process_macroblock(self, s.Y.Data, d.Y.Data, motion_h, motion_v, 16, _true) 1595 | plm_video_process_macroblock(self, s.Cr.Data, d.Cr.Data, motion_h/2, motion_v/2, 8, _true) 1596 | plm_video_process_macroblock(self, s.Cb.Data, d.Cb.Data, motion_h/2, motion_v/2, 8, _true) 1597 | } 1598 | func plm_video_process_macroblock(self *plm_video_t, s *uint8, d *uint8, motion_h int64, motion_v int64, block_size int64, interpolate int64) { 1599 | var ( 1600 | dw int64 = self.Mb_width * block_size 1601 | hp int64 = motion_h >> 1 1602 | vp int64 = motion_v >> 1 1603 | odd_h int64 = int64(libc.BoolToInt((motion_h & 1) == 1)) 1604 | odd_v int64 = int64(libc.BoolToInt((motion_v & 1) == 1)) 1605 | si uint64 = uint64(((self.Mb_row*block_size)+vp)*dw + self.Mb_col*block_size + hp) 1606 | di uint64 = uint64((self.Mb_row*dw + self.Mb_col) * block_size) 1607 | max_address uint64 = uint64(dw*(self.Mb_height*block_size-block_size+1) - block_size) 1608 | ) 1609 | if si > max_address || di > max_address { 1610 | return 1611 | } 1612 | switch (interpolate << 2) | odd_h<<1 | odd_v { 1613 | case ((0 << 2) | 0<<1 | 0): 1614 | for { 1615 | { 1616 | var ( 1617 | dest_scan int64 = dw - block_size 1618 | source_scan int64 = dw - block_size 1619 | ) 1620 | for y := int64(0); y < block_size; y++ { 1621 | for x := int64(0); x < block_size; x++ { 1622 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = *(*uint8)(unsafe.Add(unsafe.Pointer(s), si)) 1623 | si++ 1624 | di++ 1625 | } 1626 | si += uint64(source_scan) 1627 | di += uint64(dest_scan) 1628 | } 1629 | } 1630 | if _false == 0 { 1631 | break 1632 | } 1633 | } 1634 | case ((0 << 2) | 0<<1 | 1): 1635 | for { 1636 | { 1637 | var ( 1638 | dest_scan int64 = dw - block_size 1639 | source_scan int64 = dw - block_size 1640 | ) 1641 | for y := int64(0); y < block_size; y++ { 1642 | for x := int64(0); x < block_size; x++ { 1643 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+uint64(dw)))) + 1) >> 1)) 1644 | si++ 1645 | di++ 1646 | } 1647 | si += uint64(source_scan) 1648 | di += uint64(dest_scan) 1649 | } 1650 | } 1651 | if _false == 0 { 1652 | break 1653 | } 1654 | } 1655 | case ((0 << 2) | 1<<1 | 0): 1656 | for { 1657 | { 1658 | var ( 1659 | dest_scan int64 = dw - block_size 1660 | source_scan int64 = dw - block_size 1661 | ) 1662 | for y := int64(0); y < block_size; y++ { 1663 | for x := int64(0); x < block_size; x++ { 1664 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+1))) + 1) >> 1)) 1665 | si++ 1666 | di++ 1667 | } 1668 | si += uint64(source_scan) 1669 | di += uint64(dest_scan) 1670 | } 1671 | } 1672 | if _false == 0 { 1673 | break 1674 | } 1675 | } 1676 | case ((0 << 2) | 1<<1 | 1): 1677 | for { 1678 | { 1679 | var ( 1680 | dest_scan int64 = dw - block_size 1681 | source_scan int64 = dw - block_size 1682 | ) 1683 | for y := int64(0); y < block_size; y++ { 1684 | for x := int64(0); x < block_size; x++ { 1685 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+1))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+uint64(dw)))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+uint64(dw)+1))) + 2) >> 2)) 1686 | si++ 1687 | di++ 1688 | } 1689 | si += uint64(source_scan) 1690 | di += uint64(dest_scan) 1691 | } 1692 | } 1693 | if _false == 0 { 1694 | break 1695 | } 1696 | } 1697 | case ((1 << 2) | 0<<1 | 0): 1698 | for { 1699 | { 1700 | var ( 1701 | dest_scan int64 = dw - block_size 1702 | source_scan int64 = dw - block_size 1703 | ) 1704 | for y := int64(0); y < block_size; y++ { 1705 | for x := int64(0); x < block_size; x++ { 1706 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(d), di))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + 1) >> 1)) 1707 | si++ 1708 | di++ 1709 | } 1710 | si += uint64(source_scan) 1711 | di += uint64(dest_scan) 1712 | } 1713 | } 1714 | if _false == 0 { 1715 | break 1716 | } 1717 | } 1718 | case ((1 << 2) | 0<<1 | 1): 1719 | for { 1720 | { 1721 | var ( 1722 | dest_scan int64 = dw - block_size 1723 | source_scan int64 = dw - block_size 1724 | ) 1725 | for y := int64(0); y < block_size; y++ { 1726 | for x := int64(0); x < block_size; x++ { 1727 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(d), di))) + ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+uint64(dw)))) + 1) >> 1) + 1) >> 1)) 1728 | si++ 1729 | di++ 1730 | } 1731 | si += uint64(source_scan) 1732 | di += uint64(dest_scan) 1733 | } 1734 | } 1735 | if _false == 0 { 1736 | break 1737 | } 1738 | } 1739 | case ((1 << 2) | 1<<1 | 0): 1740 | for { 1741 | { 1742 | var ( 1743 | dest_scan int64 = dw - block_size 1744 | source_scan int64 = dw - block_size 1745 | ) 1746 | for y := int64(0); y < block_size; y++ { 1747 | for x := int64(0); x < block_size; x++ { 1748 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(d), di))) + ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+1))) + 1) >> 1) + 1) >> 1)) 1749 | si++ 1750 | di++ 1751 | } 1752 | si += uint64(source_scan) 1753 | di += uint64(dest_scan) 1754 | } 1755 | } 1756 | if _false == 0 { 1757 | break 1758 | } 1759 | } 1760 | case ((1 << 2) | 1<<1 | 1): 1761 | for { 1762 | { 1763 | var ( 1764 | dest_scan int64 = dw - block_size 1765 | source_scan int64 = dw - block_size 1766 | ) 1767 | for y := int64(0); y < block_size; y++ { 1768 | for x := int64(0); x < block_size; x++ { 1769 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(d), di))) + ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+1))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+uint64(dw)))) + int64(*(*uint8)(unsafe.Add(unsafe.Pointer(s), si+uint64(dw)+1))) + 2) >> 2) + 1) >> 1)) 1770 | si++ 1771 | di++ 1772 | } 1773 | si += uint64(source_scan) 1774 | di += uint64(dest_scan) 1775 | } 1776 | } 1777 | if _false == 0 { 1778 | break 1779 | } 1780 | } 1781 | } 1782 | } 1783 | func plm_video_decode_block(self *plm_video_t, block int64) { 1784 | var ( 1785 | n int64 = 0 1786 | quant_matrix *uint8 1787 | ) 1788 | if self.Macroblock_intra != 0 { 1789 | var ( 1790 | predictor int64 1791 | dct_size int64 1792 | plane_index int64 1793 | ) 1794 | if block > 3 { 1795 | plane_index = block - 3 1796 | } else { 1797 | plane_index = 0 1798 | } 1799 | predictor = self.Dc_predictor[plane_index] 1800 | dct_size = int64(plm_buffer_read_vlc(self.Buffer, plm_video_dct_size[plane_index])) 1801 | if dct_size > 0 { 1802 | var differential int64 = plm_buffer_read(self.Buffer, dct_size) 1803 | if (differential & (1 << (dct_size - 1))) != 0 { 1804 | self.Block_data[0] = predictor + differential 1805 | } else { 1806 | self.Block_data[0] = predictor + (-(1 << dct_size) | (differential + 1)) 1807 | } 1808 | } else { 1809 | self.Block_data[0] = predictor 1810 | } 1811 | self.Dc_predictor[plane_index] = self.Block_data[0] 1812 | self.Block_data[0] <<= 3 + 5 1813 | quant_matrix = &self.Intra_quant_matrix[0] 1814 | n = 1 1815 | } else { 1816 | quant_matrix = &self.Non_intra_quant_matrix[0] 1817 | } 1818 | var level int64 = 0 1819 | for _true != 0 { 1820 | var ( 1821 | run int64 = 0 1822 | coeff uint16 = plm_buffer_read_vlc_uint(self.Buffer, &plm_video_dct_coeff[0]) 1823 | ) 1824 | if int64(coeff) == 1 && n > 0 && plm_buffer_read(self.Buffer, 1) == 0 { 1825 | break 1826 | } 1827 | if int64(coeff) == math.MaxUint16 { 1828 | run = plm_buffer_read(self.Buffer, 6) 1829 | level = plm_buffer_read(self.Buffer, 8) 1830 | if level == 0 { 1831 | level = plm_buffer_read(self.Buffer, 8) 1832 | } else if level == 128 { 1833 | level = plm_buffer_read(self.Buffer, 8) - 256 1834 | } else if level > 128 { 1835 | level = level - 256 1836 | } 1837 | } else { 1838 | run = int64(coeff) >> 8 1839 | level = int64(coeff) & math.MaxUint8 1840 | if plm_buffer_read(self.Buffer, 1) != 0 { 1841 | level = -level 1842 | } 1843 | } 1844 | n += run 1845 | if n < 0 || n >= 64 { 1846 | return 1847 | } 1848 | var de_zig_zagged int64 = int64(plm_video_zig_zag[n]) 1849 | n++ 1850 | level <<= 1 1851 | if self.Macroblock_intra == 0 { 1852 | if level < 0 { 1853 | level += -1 1854 | } else { 1855 | level += 1 1856 | } 1857 | } 1858 | level = (level * self.Quantizer_scale * int64(*(*uint8)(unsafe.Add(unsafe.Pointer(quant_matrix), de_zig_zagged)))) >> 4 1859 | if (level & 1) == 0 { 1860 | if level > 0 { 1861 | level -= 1 1862 | } else { 1863 | level -= -1 1864 | } 1865 | } 1866 | if level > 2047 { 1867 | level = 2047 1868 | } else if level < -2048 { 1869 | level = -2048 1870 | } 1871 | self.Block_data[de_zig_zagged] = level * int64(plm_video_premultiplier_matrix[de_zig_zagged]) 1872 | } 1873 | var d *uint8 1874 | var dw int64 1875 | var di int64 1876 | if block < 4 { 1877 | d = self.Frame_current.Y.Data 1878 | dw = self.Luma_width 1879 | di = (self.Mb_row*self.Luma_width + self.Mb_col) << 4 1880 | if (block & 1) != 0 { 1881 | di += 8 1882 | } 1883 | if (block & 2) != 0 { 1884 | di += self.Luma_width << 3 1885 | } 1886 | } else { 1887 | if block == 4 { 1888 | d = self.Frame_current.Cb.Data 1889 | } else { 1890 | d = self.Frame_current.Cr.Data 1891 | } 1892 | dw = self.Chroma_width 1893 | di = ((self.Mb_row * self.Luma_width) << 2) + (self.Mb_col << 3) 1894 | } 1895 | var s *int64 = &self.Block_data[0] 1896 | var si int64 = 0 1897 | if self.Macroblock_intra != 0 { 1898 | if n == 1 { 1899 | var clamped int64 = int64(plm_clamp((*(*int64)(unsafe.Add(unsafe.Pointer(s), unsafe.Sizeof(int64(0))*0)) + 128) >> 8)) 1900 | for { 1901 | { 1902 | var ( 1903 | dest_scan int64 = dw - 8 1904 | source_scan int64 = 8 - 8 1905 | ) 1906 | for y := int64(0); y < 8; y++ { 1907 | for x := int64(0); x < 8; x++ { 1908 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = uint8(int8(clamped)) 1909 | si++ 1910 | di++ 1911 | } 1912 | si += source_scan 1913 | di += dest_scan 1914 | } 1915 | } 1916 | if _false == 0 { 1917 | break 1918 | } 1919 | } 1920 | *(*int64)(unsafe.Add(unsafe.Pointer(s), unsafe.Sizeof(int64(0))*0)) = 0 1921 | } else { 1922 | plm_video_idct(s) 1923 | for { 1924 | { 1925 | var ( 1926 | dest_scan int64 = dw - 8 1927 | source_scan int64 = 8 - 8 1928 | ) 1929 | for y := int64(0); y < 8; y++ { 1930 | for x := int64(0); x < 8; x++ { 1931 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = plm_clamp(*(*int64)(unsafe.Add(unsafe.Pointer(s), unsafe.Sizeof(int64(0))*uintptr(si)))) 1932 | si++ 1933 | di++ 1934 | } 1935 | si += source_scan 1936 | di += dest_scan 1937 | } 1938 | } 1939 | if _false == 0 { 1940 | break 1941 | } 1942 | } 1943 | *(*[64]int64)(unsafe.Pointer(&self.Block_data[0])) = [64]int64{} 1944 | } 1945 | } else { 1946 | if n == 1 { 1947 | var value int64 = (*(*int64)(unsafe.Add(unsafe.Pointer(s), unsafe.Sizeof(int64(0))*0)) + 128) >> 8 1948 | for { 1949 | { 1950 | var ( 1951 | dest_scan int64 = dw - 8 1952 | source_scan int64 = 8 - 8 1953 | ) 1954 | for y := int64(0); y < 8; y++ { 1955 | for x := int64(0); x < 8; x++ { 1956 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = plm_clamp(int64(*(*uint8)(unsafe.Add(unsafe.Pointer(d), di))) + value) 1957 | si++ 1958 | di++ 1959 | } 1960 | si += source_scan 1961 | di += dest_scan 1962 | } 1963 | } 1964 | if _false == 0 { 1965 | break 1966 | } 1967 | } 1968 | *(*int64)(unsafe.Add(unsafe.Pointer(s), unsafe.Sizeof(int64(0))*0)) = 0 1969 | } else { 1970 | plm_video_idct(s) 1971 | for { 1972 | { 1973 | var ( 1974 | dest_scan int64 = dw - 8 1975 | source_scan int64 = 8 - 8 1976 | ) 1977 | for y := int64(0); y < 8; y++ { 1978 | for x := int64(0); x < 8; x++ { 1979 | *(*uint8)(unsafe.Add(unsafe.Pointer(d), di)) = plm_clamp(int64(*(*uint8)(unsafe.Add(unsafe.Pointer(d), di))) + *(*int64)(unsafe.Add(unsafe.Pointer(s), unsafe.Sizeof(int64(0))*uintptr(si)))) 1980 | si++ 1981 | di++ 1982 | } 1983 | si += source_scan 1984 | di += dest_scan 1985 | } 1986 | } 1987 | if _false == 0 { 1988 | break 1989 | } 1990 | } 1991 | *(*[64]int64)(unsafe.Pointer(&self.Block_data[0])) = [64]int64{} 1992 | } 1993 | } 1994 | } 1995 | func plm_video_idct(block *int64) { 1996 | var ( 1997 | b1 int64 1998 | b3 int64 1999 | b4 int64 2000 | b6 int64 2001 | b7 int64 2002 | tmp1 int64 2003 | tmp2 int64 2004 | m0 int64 2005 | x0 int64 2006 | x1 int64 2007 | x2 int64 2008 | x3 int64 2009 | x4 int64 2010 | y3 int64 2011 | y4 int64 2012 | y5 int64 2013 | y6 int64 2014 | y7 int64 2015 | ) 2016 | for i := int64(0); i < 8; i++ { 2017 | b1 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+4*8))) 2018 | b3 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+2*8))) + *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+6*8))) 2019 | b4 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+5*8))) - *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+3*8))) 2020 | tmp1 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+1*8))) + *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+7*8))) 2021 | tmp2 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+3*8))) + *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+5*8))) 2022 | b6 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+1*8))) - *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+7*8))) 2023 | b7 = tmp1 + tmp2 2024 | m0 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+0*8))) 2025 | x4 = ((b6*473 - b4*196 + 128) >> 8) - b7 2026 | x0 = x4 - (((tmp1-tmp2)*362 + 128) >> 8) 2027 | x1 = m0 - b1 2028 | x2 = (((*(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+2*8)))-*(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+6*8))))*362 + 128) >> 8) - b3 2029 | x3 = m0 + b1 2030 | y3 = x1 + x2 2031 | y4 = x3 + b3 2032 | y5 = x1 - x2 2033 | y6 = x3 - b3 2034 | y7 = -x0 - ((b4*473 + b6*196 + 128) >> 8) 2035 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+0*8))) = b7 + y4 2036 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+1*8))) = x4 + y3 2037 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+2*8))) = y5 - x0 2038 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+3*8))) = y6 - y7 2039 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+4*8))) = y6 + y7 2040 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+5*8))) = x0 + y5 2041 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+6*8))) = y3 - x4 2042 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+7*8))) = y4 - b7 2043 | } 2044 | for i := int64(0); i < 64; i += 8 { 2045 | b1 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+4))) 2046 | b3 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+2))) + *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+6))) 2047 | b4 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+5))) - *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+3))) 2048 | tmp1 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+1))) + *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+7))) 2049 | tmp2 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+3))) + *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+5))) 2050 | b6 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+1))) - *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+7))) 2051 | b7 = tmp1 + tmp2 2052 | m0 = *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+0))) 2053 | x4 = ((b6*473 - b4*196 + 128) >> 8) - b7 2054 | x0 = x4 - (((tmp1-tmp2)*362 + 128) >> 8) 2055 | x1 = m0 - b1 2056 | x2 = (((*(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+2)))-*(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+6))))*362 + 128) >> 8) - b3 2057 | x3 = m0 + b1 2058 | y3 = x1 + x2 2059 | y4 = x3 + b3 2060 | y5 = x1 - x2 2061 | y6 = x3 - b3 2062 | y7 = -x0 - ((b4*473 + b6*196 + 128) >> 8) 2063 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+0))) = (b7 + y4 + 128) >> 8 2064 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+1))) = (x4 + y3 + 128) >> 8 2065 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+2))) = (y5 - x0 + 128) >> 8 2066 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+3))) = (y6 - y7 + 128) >> 8 2067 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+4))) = (y6 + y7 + 128) >> 8 2068 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+5))) = (x0 + y5 + 128) >> 8 2069 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+6))) = (y3 - x4 + 128) >> 8 2070 | *(*int64)(unsafe.Add(unsafe.Pointer(block), unsafe.Sizeof(int64(0))*uintptr(i+7))) = (y4 - b7 + 128) >> 8 2071 | } 2072 | } 2073 | func plm_frame_to_rgb(frame *plm_frame_t, dest *uint8, stride int64) { 2074 | var ( 2075 | cols int64 = int64(frame.Width >> 1) 2076 | rows int64 = int64(frame.Height >> 1) 2077 | yw int64 = int64(frame.Y.Width) 2078 | cw int64 = int64(frame.Cb.Width) 2079 | ) 2080 | for row := int64(0); row < rows; row++ { 2081 | var ( 2082 | c_index int64 = row * cw 2083 | y_index int64 = row * 2 * yw 2084 | d_index int64 = row * 2 * stride 2085 | ) 2086 | for col := int64(0); col < cols; col++ { 2087 | var ( 2088 | y int64 2089 | cr int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cr.Data), c_index))) - 128 2090 | cb int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cb.Data), c_index))) - 128 2091 | r int64 = (cr * 0x19895) >> 16 2092 | g int64 = (cb*0x644A + cr*0xD01E) >> 16 2093 | b int64 = (cb * 0x20469) >> 16 2094 | ) 2095 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+0))) - 16) * 76309) >> 16 2096 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+0)) = plm_clamp(y + r) 2097 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+1)) = plm_clamp(y - g) 2098 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+2)) = plm_clamp(y + b) 2099 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+1))) - 16) * 76309) >> 16 2100 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+3+0)) = plm_clamp(y + r) 2101 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+3+1)) = plm_clamp(y - g) 2102 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+3+2)) = plm_clamp(y + b) 2103 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw))) - 16) * 76309) >> 16 2104 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+0)) = plm_clamp(y + r) 2105 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+1)) = plm_clamp(y - g) 2106 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+2)) = plm_clamp(y + b) 2107 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw+1))) - 16) * 76309) >> 16 2108 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3+0)) = plm_clamp(y + r) 2109 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3+1)) = plm_clamp(y - g) 2110 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3+2)) = plm_clamp(y + b) 2111 | c_index += 1 2112 | y_index += 2 2113 | d_index += 2 * 3 2114 | } 2115 | } 2116 | } 2117 | func plm_frame_to_bgr(frame *plm_frame_t, dest *uint8, stride int64) { 2118 | var ( 2119 | cols int64 = int64(frame.Width >> 1) 2120 | rows int64 = int64(frame.Height >> 1) 2121 | yw int64 = int64(frame.Y.Width) 2122 | cw int64 = int64(frame.Cb.Width) 2123 | ) 2124 | for row := int64(0); row < rows; row++ { 2125 | var ( 2126 | c_index int64 = row * cw 2127 | y_index int64 = row * 2 * yw 2128 | d_index int64 = row * 2 * stride 2129 | ) 2130 | for col := int64(0); col < cols; col++ { 2131 | var ( 2132 | y int64 2133 | cr int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cr.Data), c_index))) - 128 2134 | cb int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cb.Data), c_index))) - 128 2135 | r int64 = (cr * 0x19895) >> 16 2136 | g int64 = (cb*0x644A + cr*0xD01E) >> 16 2137 | b int64 = (cb * 0x20469) >> 16 2138 | ) 2139 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+0))) - 16) * 76309) >> 16 2140 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+2)) = plm_clamp(y + r) 2141 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+1)) = plm_clamp(y - g) 2142 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+0)) = plm_clamp(y + b) 2143 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+1))) - 16) * 76309) >> 16 2144 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+3+2)) = plm_clamp(y + r) 2145 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+3+1)) = plm_clamp(y - g) 2146 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+3+0)) = plm_clamp(y + b) 2147 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw))) - 16) * 76309) >> 16 2148 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+2)) = plm_clamp(y + r) 2149 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+1)) = plm_clamp(y - g) 2150 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+0)) = plm_clamp(y + b) 2151 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw+1))) - 16) * 76309) >> 16 2152 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3+2)) = plm_clamp(y + r) 2153 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3+1)) = plm_clamp(y - g) 2154 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3+0)) = plm_clamp(y + b) 2155 | c_index += 1 2156 | y_index += 2 2157 | d_index += 2 * 3 2158 | } 2159 | } 2160 | } 2161 | func plm_frame_to_rgba(frame *plm_frame_t, dest *uint8, stride int64) { 2162 | var ( 2163 | cols int64 = int64(frame.Width >> 1) 2164 | rows int64 = int64(frame.Height >> 1) 2165 | yw int64 = int64(frame.Y.Width) 2166 | cw int64 = int64(frame.Cb.Width) 2167 | ) 2168 | for row := int64(0); row < rows; row++ { 2169 | var ( 2170 | c_index int64 = row * cw 2171 | y_index int64 = row * 2 * yw 2172 | d_index int64 = row * 2 * stride 2173 | ) 2174 | for col := int64(0); col < cols; col++ { 2175 | var ( 2176 | y int64 2177 | cr int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cr.Data), c_index))) - 128 2178 | cb int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cb.Data), c_index))) - 128 2179 | r int64 = (cr * 0x19895) >> 16 2180 | g int64 = (cb*0x644A + cr*0xD01E) >> 16 2181 | b int64 = (cb * 0x20469) >> 16 2182 | ) 2183 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+0))) - 16) * 76309) >> 16 2184 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+0)) = plm_clamp(y + r) 2185 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+1)) = plm_clamp(y - g) 2186 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+2)) = plm_clamp(y + b) 2187 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+1))) - 16) * 76309) >> 16 2188 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+0)) = plm_clamp(y + r) 2189 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+1)) = plm_clamp(y - g) 2190 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+2)) = plm_clamp(y + b) 2191 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw))) - 16) * 76309) >> 16 2192 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+0)) = plm_clamp(y + r) 2193 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+1)) = plm_clamp(y - g) 2194 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+2)) = plm_clamp(y + b) 2195 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw+1))) - 16) * 76309) >> 16 2196 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+0)) = plm_clamp(y + r) 2197 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+1)) = plm_clamp(y - g) 2198 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+2)) = plm_clamp(y + b) 2199 | c_index += 1 2200 | y_index += 2 2201 | d_index += 2 * 4 2202 | } 2203 | } 2204 | } 2205 | func plm_frame_to_bgra(frame *plm_frame_t, dest *uint8, stride int64) { 2206 | var ( 2207 | cols int64 = int64(frame.Width >> 1) 2208 | rows int64 = int64(frame.Height >> 1) 2209 | yw int64 = int64(frame.Y.Width) 2210 | cw int64 = int64(frame.Cb.Width) 2211 | ) 2212 | for row := int64(0); row < rows; row++ { 2213 | var ( 2214 | c_index int64 = row * cw 2215 | y_index int64 = row * 2 * yw 2216 | d_index int64 = row * 2 * stride 2217 | ) 2218 | for col := int64(0); col < cols; col++ { 2219 | var ( 2220 | y int64 2221 | cr int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cr.Data), c_index))) - 128 2222 | cb int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cb.Data), c_index))) - 128 2223 | r int64 = (cr * 0x19895) >> 16 2224 | g int64 = (cb*0x644A + cr*0xD01E) >> 16 2225 | b int64 = (cb * 0x20469) >> 16 2226 | ) 2227 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+0))) - 16) * 76309) >> 16 2228 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+2)) = plm_clamp(y + r) 2229 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+1)) = plm_clamp(y - g) 2230 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+0)) = plm_clamp(y + b) 2231 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+1))) - 16) * 76309) >> 16 2232 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+2)) = plm_clamp(y + r) 2233 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+1)) = plm_clamp(y - g) 2234 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+0)) = plm_clamp(y + b) 2235 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw))) - 16) * 76309) >> 16 2236 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+2)) = plm_clamp(y + r) 2237 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+1)) = plm_clamp(y - g) 2238 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+0)) = plm_clamp(y + b) 2239 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw+1))) - 16) * 76309) >> 16 2240 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+2)) = plm_clamp(y + r) 2241 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+1)) = plm_clamp(y - g) 2242 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+0)) = plm_clamp(y + b) 2243 | c_index += 1 2244 | y_index += 2 2245 | d_index += 2 * 4 2246 | } 2247 | } 2248 | } 2249 | func plm_frame_to_argb(frame *plm_frame_t, dest *uint8, stride int64) { 2250 | var ( 2251 | cols int64 = int64(frame.Width >> 1) 2252 | rows int64 = int64(frame.Height >> 1) 2253 | yw int64 = int64(frame.Y.Width) 2254 | cw int64 = int64(frame.Cb.Width) 2255 | ) 2256 | for row := int64(0); row < rows; row++ { 2257 | var ( 2258 | c_index int64 = row * cw 2259 | y_index int64 = row * 2 * yw 2260 | d_index int64 = row * 2 * stride 2261 | ) 2262 | for col := int64(0); col < cols; col++ { 2263 | var ( 2264 | y int64 2265 | cr int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cr.Data), c_index))) - 128 2266 | cb int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cb.Data), c_index))) - 128 2267 | r int64 = (cr * 0x19895) >> 16 2268 | g int64 = (cb*0x644A + cr*0xD01E) >> 16 2269 | b int64 = (cb * 0x20469) >> 16 2270 | ) 2271 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+0))) - 16) * 76309) >> 16 2272 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+1)) = plm_clamp(y + r) 2273 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+2)) = plm_clamp(y - g) 2274 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+3)) = plm_clamp(y + b) 2275 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+1))) - 16) * 76309) >> 16 2276 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+1)) = plm_clamp(y + r) 2277 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+2)) = plm_clamp(y - g) 2278 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+3)) = plm_clamp(y + b) 2279 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw))) - 16) * 76309) >> 16 2280 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+1)) = plm_clamp(y + r) 2281 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+2)) = plm_clamp(y - g) 2282 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3)) = plm_clamp(y + b) 2283 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw+1))) - 16) * 76309) >> 16 2284 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+1)) = plm_clamp(y + r) 2285 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+2)) = plm_clamp(y - g) 2286 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+3)) = plm_clamp(y + b) 2287 | c_index += 1 2288 | y_index += 2 2289 | d_index += 2 * 4 2290 | } 2291 | } 2292 | } 2293 | func plm_frame_to_abgr(frame *plm_frame_t, dest *uint8, stride int64) { 2294 | var ( 2295 | cols int64 = int64(frame.Width >> 1) 2296 | rows int64 = int64(frame.Height >> 1) 2297 | yw int64 = int64(frame.Y.Width) 2298 | cw int64 = int64(frame.Cb.Width) 2299 | ) 2300 | for row := int64(0); row < rows; row++ { 2301 | var ( 2302 | c_index int64 = row * cw 2303 | y_index int64 = row * 2 * yw 2304 | d_index int64 = row * 2 * stride 2305 | ) 2306 | for col := int64(0); col < cols; col++ { 2307 | var ( 2308 | y int64 2309 | cr int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cr.Data), c_index))) - 128 2310 | cb int64 = int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Cb.Data), c_index))) - 128 2311 | r int64 = (cr * 0x19895) >> 16 2312 | g int64 = (cb*0x644A + cr*0xD01E) >> 16 2313 | b int64 = (cb * 0x20469) >> 16 2314 | ) 2315 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+0))) - 16) * 76309) >> 16 2316 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+3)) = plm_clamp(y + r) 2317 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+2)) = plm_clamp(y - g) 2318 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+0+1)) = plm_clamp(y + b) 2319 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+1))) - 16) * 76309) >> 16 2320 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+3)) = plm_clamp(y + r) 2321 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+2)) = plm_clamp(y - g) 2322 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+4+1)) = plm_clamp(y + b) 2323 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw))) - 16) * 76309) >> 16 2324 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+3)) = plm_clamp(y + r) 2325 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+2)) = plm_clamp(y - g) 2326 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+1)) = plm_clamp(y + b) 2327 | y = ((int64(*(*uint8)(unsafe.Add(unsafe.Pointer(frame.Y.Data), y_index+yw+1))) - 16) * 76309) >> 16 2328 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+3)) = plm_clamp(y + r) 2329 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+2)) = plm_clamp(y - g) 2330 | *(*uint8)(unsafe.Add(unsafe.Pointer(dest), d_index+stride+4+1)) = plm_clamp(y + b) 2331 | c_index += 1 2332 | y_index += 2 2333 | d_index += 2 * 4 2334 | } 2335 | } 2336 | } 2337 | 2338 | var plm_audio_frame_sync int64 = 2047 2339 | var plm_audio_mpeg_2_5 int64 = 0 2340 | var plm_audio_mpeg_2 int64 = 2 2341 | var plm_audio_mpeg_1 int64 = 3 2342 | var plm_audio_layer_iii int64 = 1 2343 | var plm_audio_layer_ii int64 = 2 2344 | var plm_audio_layer_i int64 = 3 2345 | var plm_audio_mode_stereo int64 = 0 2346 | var plm_audio_mode_joint_stereo int64 = 1 2347 | var plm_audio_mode_dual_channel int64 = 2 2348 | var plm_audio_mode_mono int64 = 3 2349 | var plm_audio_sample_rate [8]uint16 = [8]uint16{44100, 48000, 32000, 0, 22050, 24000, 16000, 0} 2350 | var plm_audio_bit_rate [28]int16 = [28]int16{32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} 2351 | var plm_audio_scalefactor_base [3]int64 = [3]int64{0x2000000, 26632170, 0x1428A30} 2352 | var plm_audio_synthesis_window [512]float32 = [512]float32{0.0, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -1.0, -1.0, -1.0, -1.0, -1.5, -1.5, -2.0, -2.0, -2.5, -2.5, -3.0, -3.5, -3.5, -4.0, -4.5, -5.0, -5.5, -6.5, -7.0, -8.0, -8.5, -9.5, -10.5, -12.0, -13.0, -14.5, -15.5, -17.5, -19.0, -20.5, -22.5, -24.5, -26.5, -29.0, -31.5, -34.0, -36.5, -39.5, -42.5, -45.5, -48.5, -52.0, -55.5, -58.5, -62.5, -66.0, -69.5, -73.5, -77.0, -80.5, -84.5, -88.0, -91.5, -95.0, -98.0, -101.0, -104.0, 106.5, 109.0, 111.0, 112.5, 113.5, 114.0, 114.0, 113.5, 112.0, 110.5, 107.5, 104.0, 100.0, 94.5, 88.5, 81.5, 73.0, 63.5, 53.0, 41.5, 28.5, 14.5, -1.0, -18.0, -36.0, -55.5, -76.5, -98.5, -122.0, -147.0, -173.5, -200.5, -229.5, -259.5, -290.5, -322.5, -355.5, -389.5, -424.0, -459.5, -495.5, -532.0, -568.5, -605.0, -641.5, -678.0, -714.0, -749.0, -783.5, -817.0, -849.0, -879.5, -908.5, -935.0, -959.5, -981.0, -1000.5, -1016.0, -1028.5, -1037.5, -1042.5, -1043.5, -1040.0, -1031.5, 1018.5, 1000.0, 976.0, 946.5, 911.0, 869.5, 822.0, 767.5, 707.0, 640.0, 565.5, 485.0, 397.0, 302.5, 201.0, 92.5, -22.5, -144.0, -272.5, -407.0, -547.5, -694.0, -846.0, -1003.0, -1165.0, -1331.5, -1502.0, -1675.5, -1852.5, -2031.5, -2212.5, -2394.0, -2576.5, -2758.5, -2939.5, -3118.5, -3294.5, -3467.5, -3635.5, -3798.5, -3955.0, -4104.5, -4245.5, -4377.5, -4499.0, -4609.5, -4708.0, -4792.5, -4863.5, -4919.0, -4958.0, -4979.5, -4983.0, -4967.5, -4931.5, -4875.0, -4796.0, -4694.5, -4569.5, -4420.0, -4246.0, -4046.0, -3820.0, -3567.0, 3287.0, 2979.5, 2644.0, 2280.5, 1888.0, 1467.5, 1018.5, 541.0, 35.0, -499.0, -1061.0, -1650.0, -2266.5, -2909.0, -3577.0, -4270.0, -4987.5, -5727.5, -6490.0, -7274.0, -8077.5, -8899.5, -9739.0, -10594.5, -11464.5, -12347.0, -13241.0, -14144.5, -15056.0, -15973.5, -16895.5, -17820.0, -18744.5, -19668.0, -20588.0, -21503.0, -22410.5, -23308.5, -24195.0, -25068.5, -25926.5, -26767.0, -27589.0, -28389.0, -29166.5, -29919.0, -30644.5, -31342.0, -32009.5, -32645.0, -33247.0, -33814.5, -34346.0, -34839.5, -35295.0, -35710.0, -36084.5, -36417.5, -36707.5, -36954.0, -37156.5, -37315.0, -37428.0, -37496.0, 37519.0, 37496.0, 37428.0, 37315.0, 37156.5, 36954.0, 36707.5, 36417.5, 36084.5, 35710.0, 35295.0, 34839.5, 34346.0, 33814.5, 33247.0, 32645.0, 32009.5, 31342.0, 30644.5, 29919.0, 29166.5, 28389.0, 27589.0, 26767.0, 25926.5, 25068.5, 24195.0, 23308.5, 22410.5, 21503.0, 20588.0, 19668.0, 18744.5, 17820.0, 16895.5, 15973.5, 15056.0, 14144.5, 13241.0, 12347.0, 11464.5, 10594.5, 9739.0, 8899.5, 8077.5, 7274.0, 6490.0, 5727.5, 4987.5, 4270.0, 3577.0, 2909.0, 2266.5, 1650.0, 1061.0, 499.0, -35.0, -541.0, -1018.5, -1467.5, -1888.0, -2280.5, -2644.0, -2979.5, 3287.0, 3567.0, 3820.0, 4046.0, 4246.0, 4420.0, 4569.5, 4694.5, 4796.0, 4875.0, 4931.5, 4967.5, 4983.0, 4979.5, 4958.0, 4919.0, 4863.5, 4792.5, 4708.0, 4609.5, 4499.0, 4377.5, 4245.5, 4104.5, 3955.0, 3798.5, 3635.5, 3467.5, 3294.5, 3118.5, 2939.5, 2758.5, 2576.5, 2394.0, 2212.5, 2031.5, 1852.5, 1675.5, 1502.0, 1331.5, 1165.0, 1003.0, 846.0, 694.0, 547.5, 407.0, 272.5, 144.0, 22.5, -92.5, -201.0, -302.5, -397.0, -485.0, -565.5, -640.0, -707.0, -767.5, -822.0, -869.5, -911.0, -946.5, -976.0, -1000.0, 1018.5, 1031.5, 1040.0, 1043.5, 1042.5, 1037.5, 1028.5, 1016.0, 1000.5, 981.0, 959.5, 935.0, 908.5, 879.5, 849.0, 817.0, 783.5, 749.0, 714.0, 678.0, 641.5, 605.0, 568.5, 532.0, 495.5, 459.5, 424.0, 389.5, 355.5, 322.5, 290.5, 259.5, 229.5, 200.5, 173.5, 147.0, 122.0, 98.5, 76.5, 55.5, 36.0, 18.0, 1.0, -14.5, -28.5, -41.5, -53.0, -63.5, -73.0, -81.5, -88.5, -94.5, -100.0, -104.0, -107.5, -110.5, -112.0, -113.5, -114.0, -114.0, -113.5, -112.5, -111.0, -109.0, 106.5, 104.0, 101.0, 98.0, 95.0, 91.5, 88.0, 84.5, 80.5, 77.0, 73.5, 69.5, 66.0, 62.5, 58.5, 55.5, 52.0, 48.5, 45.5, 42.5, 39.5, 36.5, 34.0, 31.5, 29.0, 26.5, 24.5, 22.5, 20.5, 19.0, 17.5, 15.5, 14.5, 13.0, 12.0, 10.5, 9.5, 8.5, 8.0, 7.0, 6.5, 5.5, 5.0, 4.5, 4.0, 3.5, 3.5, 3.0, 2.5, 2.5, 2.0, 2.0, 1.5, 1.5, 1.0, 1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5} 2353 | var plm_audio_quant_lut_step_1 [2][16]uint8 = [2][16]uint8{{0: 0, 1: 0, 2: 1, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2, 9: 2, 10: 2, 11: 2, 12: 2, 13: 2}, {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 1, 7: 1, 8: 1, 9: 2, 10: 2, 11: 2, 12: 2, 13: 2}} 2354 | var plm_audio_quant_tab_A uint8 = (27 | 64) 2355 | var plm_audio_quant_tab_B uint8 = (30 | 64) 2356 | var plm_audio_quant_tab_C uint8 = 8 2357 | var plm_audio_quant_tab_D uint8 = 12 2358 | var quant_lut_step_2 [3][3]uint8 = [3][3]uint8{{plm_audio_quant_tab_C, plm_audio_quant_tab_C, plm_audio_quant_tab_D}, {plm_audio_quant_tab_A, plm_audio_quant_tab_A, plm_audio_quant_tab_A}, {plm_audio_quant_tab_B, plm_audio_quant_tab_A, plm_audio_quant_tab_B}} 2359 | var plm_audio_quant_lut_step_3 [3][32]uint8 = [3][32]uint8{{0: 68, 1: 68, 2: 52, 3: 52, 4: 52, 5: 52, 6: 52, 7: 52, 8: 52, 9: 52, 10: 52, 11: 52}, {0: 67, 1: 67, 2: 67, 3: 66, 4: 66, 5: 66, 6: 66, 7: 66, 8: 66, 9: 66, 10: 66, 11: 49, 12: 49, 13: 49, 14: 49, 15: 49, 16: 49, 17: 49, 18: 49, 19: 49, 20: 49, 21: 49, 22: 49, 23: 32, 24: 32, 25: 32, 26: 32, 27: 32, 28: 32, 29: 32}, {0: 69, 1: 69, 2: 69, 3: 69, 4: 52, 5: 52, 6: 52, 7: 52, 8: 52, 9: 52, 10: 52, 11: 36, 12: 36, 13: 36, 14: 36, 15: 36, 16: 36, 17: 36, 18: 36, 19: 36, 20: 36, 21: 36, 22: 36, 23: 36, 24: 36, 25: 36, 26: 36, 27: 36, 28: 36, 29: 36}} 2360 | var plm_audio_quant_lut_step_4 [6][16]uint8 = [6][16]uint8{{0: 0, 1: 1, 2: 2, 3: 17}, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 17}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17}, {0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}} 2361 | 2362 | type plm_quantizer_spec_t struct { 2363 | Levels uint16 2364 | Group uint8 2365 | Bits uint8 2366 | } 2367 | 2368 | var plm_audio_quant_tab [17]plm_quantizer_spec_t = [17]plm_quantizer_spec_t{{Levels: 3, Group: 1, Bits: 5}, {Levels: 5, Group: 1, Bits: 7}, {Levels: 7, Group: 0, Bits: 3}, {Levels: 9, Group: 1, Bits: 10}, {Levels: 15, Group: 0, Bits: 4}, {Levels: 31, Group: 0, Bits: 5}, {Levels: 63, Group: 0, Bits: 6}, {Levels: math.MaxInt8, Group: 0, Bits: 7}, {Levels: math.MaxUint8, Group: 0, Bits: 8}, {Levels: 511, Group: 0, Bits: 9}, {Levels: 1023, Group: 0, Bits: 10}, {Levels: 2047, Group: 0, Bits: 11}, {Levels: 4095, Group: 0, Bits: 12}, {Levels: 8191, Group: 0, Bits: 13}, {Levels: 0x3FFF, Group: 0, Bits: 14}, {Levels: math.MaxInt16, Group: 0, Bits: 15}, {Levels: math.MaxUint16, Group: 0, Bits: 16}} 2369 | 2370 | func plm_audio_create_with_buffer(buffer *plm_buffer_t, destroy_when_done int64) *plm_audio_t { 2371 | var self *plm_audio_t = new(plm_audio_t) 2372 | *self = plm_audio_t{} 2373 | self.Samples.Count = plm_audio_samples_per_frame 2374 | self.Buffer = buffer 2375 | self.Destroy_buffer_when_done = destroy_when_done 2376 | self.Samplerate_index = 3 2377 | libc.MemCpy(unsafe.Pointer(&self.D[0]), unsafe.Pointer(&plm_audio_synthesis_window[0]), int(512*unsafe.Sizeof(float32(0)))) 2378 | libc.MemCpy(unsafe.Pointer(&self.D[512]), unsafe.Pointer(&plm_audio_synthesis_window[0]), int(512*unsafe.Sizeof(float32(0)))) 2379 | self.Next_frame_data_size = plm_audio_decode_header(self) 2380 | return self 2381 | } 2382 | func plm_audio_destroy(self *plm_audio_t) { 2383 | if self.Destroy_buffer_when_done != 0 { 2384 | plm_buffer_destroy(self.Buffer) 2385 | } 2386 | libc.Free(unsafe.Pointer(self)) 2387 | } 2388 | func plm_audio_has_header(self *plm_audio_t) int64 { 2389 | if self.Has_header != 0 { 2390 | return _true 2391 | } 2392 | self.Next_frame_data_size = plm_audio_decode_header(self) 2393 | return self.Has_header 2394 | } 2395 | func plm_audio_get_samplerate(self *plm_audio_t) int64 { 2396 | if plm_audio_has_header(self) != 0 { 2397 | return int64(plm_audio_sample_rate[self.Samplerate_index]) 2398 | } 2399 | return 0 2400 | } 2401 | func plm_audio_get_time(self *plm_audio_t) float64 { 2402 | return self.Time 2403 | } 2404 | func plm_audio_set_time(self *plm_audio_t, time float64) { 2405 | self.Samples_decoded = int64(time * float64(plm_audio_sample_rate[self.Samplerate_index])) 2406 | self.Time = time 2407 | } 2408 | func plm_audio_rewind(self *plm_audio_t) { 2409 | plm_buffer_rewind(self.Buffer) 2410 | self.Time = 0 2411 | self.Samples_decoded = 0 2412 | self.Next_frame_data_size = 0 2413 | } 2414 | func plm_audio_has_ended(self *plm_audio_t) int64 { 2415 | return plm_buffer_has_ended(self.Buffer) 2416 | } 2417 | func plm_audio_decode(self *plm_audio_t) *plm_samples_t { 2418 | if self.Next_frame_data_size == 0 { 2419 | if plm_buffer_has(self.Buffer, 48) == 0 { 2420 | return nil 2421 | } 2422 | self.Next_frame_data_size = plm_audio_decode_header(self) 2423 | } 2424 | if self.Next_frame_data_size == 0 || plm_buffer_has(self.Buffer, uint64(self.Next_frame_data_size<<3)) == 0 { 2425 | return nil 2426 | } 2427 | plm_audio_decode_frame(self) 2428 | self.Next_frame_data_size = 0 2429 | self.Samples.Time = self.Time 2430 | self.Samples_decoded += plm_audio_samples_per_frame 2431 | self.Time = float64(self.Samples_decoded) / float64(plm_audio_sample_rate[self.Samplerate_index]) 2432 | return &self.Samples 2433 | } 2434 | func plm_audio_find_frame_sync(self *plm_audio_t) int64 { 2435 | var i uint64 2436 | for i = self.Buffer.Bit_index >> 3; i < self.Buffer.Length-1; i++ { 2437 | if int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Buffer.Bytes), i))) == math.MaxUint8 && (int64(*(*uint8)(unsafe.Add(unsafe.Pointer(self.Buffer.Bytes), i+1)))&254) == 252 { 2438 | self.Buffer.Bit_index = ((i + 1) << 3) + 3 2439 | return _true 2440 | } 2441 | } 2442 | self.Buffer.Bit_index = (i + 1) << 3 2443 | return _false 2444 | } 2445 | func plm_audio_decode_header(self *plm_audio_t) int64 { 2446 | if plm_buffer_has(self.Buffer, 48) == 0 { 2447 | return 0 2448 | } 2449 | plm_buffer_skip_bytes(self.Buffer, 0) 2450 | var sync int64 = plm_buffer_read(self.Buffer, 11) 2451 | if sync != plm_audio_frame_sync && plm_audio_find_frame_sync(self) == 0 { 2452 | return 0 2453 | } 2454 | self.Version = plm_buffer_read(self.Buffer, 2) 2455 | self.Layer = plm_buffer_read(self.Buffer, 2) 2456 | var hasCRC int64 = int64(libc.BoolToInt(plm_buffer_read(self.Buffer, 1) == 0)) 2457 | if self.Version != plm_audio_mpeg_1 || self.Layer != plm_audio_layer_ii { 2458 | return 0 2459 | } 2460 | var bitrate_index int64 = plm_buffer_read(self.Buffer, 4) - 1 2461 | if bitrate_index > 13 { 2462 | return 0 2463 | } 2464 | var samplerate_index int64 = plm_buffer_read(self.Buffer, 2) 2465 | if samplerate_index == 3 { 2466 | return 0 2467 | } 2468 | var padding int64 = plm_buffer_read(self.Buffer, 1) 2469 | plm_buffer_skip(self.Buffer, 1) 2470 | var mode int64 = plm_buffer_read(self.Buffer, 2) 2471 | if self.Has_header != 0 && (self.Bitrate_index != bitrate_index || self.Samplerate_index != samplerate_index || self.Mode != mode) { 2472 | return 0 2473 | } 2474 | self.Bitrate_index = bitrate_index 2475 | self.Samplerate_index = samplerate_index 2476 | self.Mode = mode 2477 | self.Has_header = _true 2478 | if mode == plm_audio_mode_joint_stereo { 2479 | self.Bound = (plm_buffer_read(self.Buffer, 2) + 1) << 2 2480 | } else { 2481 | plm_buffer_skip(self.Buffer, 2) 2482 | if mode == plm_audio_mode_mono { 2483 | self.Bound = 0 2484 | } else { 2485 | self.Bound = 32 2486 | } 2487 | } 2488 | plm_buffer_skip(self.Buffer, 4) 2489 | if hasCRC != 0 { 2490 | plm_buffer_skip(self.Buffer, 16) 2491 | } 2492 | var bitrate int64 = int64(plm_audio_bit_rate[self.Bitrate_index]) 2493 | var samplerate int64 = int64(plm_audio_sample_rate[self.Samplerate_index]) 2494 | var frame_size int64 = (bitrate * 144000 / samplerate) + padding 2495 | return frame_size - (func() int64 { 2496 | if hasCRC != 0 { 2497 | return 6 2498 | } 2499 | return 4 2500 | }()) 2501 | } 2502 | func plm_audio_decode_frame(self *plm_audio_t) { 2503 | var ( 2504 | tab3 int64 = 0 2505 | sblimit int64 = 0 2506 | tab1 int64 2507 | ) 2508 | if self.Mode == plm_audio_mode_mono { 2509 | tab1 = 0 2510 | } else { 2511 | tab1 = 1 2512 | } 2513 | var tab2 int64 = int64(plm_audio_quant_lut_step_1[tab1][self.Bitrate_index]) 2514 | tab3 = int64(quant_lut_step_2[tab2][self.Samplerate_index]) 2515 | sblimit = tab3 & 63 2516 | tab3 >>= 6 2517 | if self.Bound > sblimit { 2518 | self.Bound = sblimit 2519 | } 2520 | for sb := int64(0); sb < self.Bound; sb++ { 2521 | self.Allocation[0][sb] = plm_audio_read_allocation(self, sb, tab3) 2522 | self.Allocation[1][sb] = plm_audio_read_allocation(self, sb, tab3) 2523 | } 2524 | for sb := int64(self.Bound); sb < sblimit; sb++ { 2525 | self.Allocation[0][sb] = func() *plm_quantizer_spec_t { 2526 | p := &self.Allocation[1][sb] 2527 | self.Allocation[1][sb] = plm_audio_read_allocation(self, sb, tab3) 2528 | return *p 2529 | }() 2530 | } 2531 | var channels int64 2532 | if self.Mode == plm_audio_mode_mono { 2533 | channels = 1 2534 | } else { 2535 | channels = 2 2536 | } 2537 | for sb := int64(0); sb < sblimit; sb++ { 2538 | for ch := int64(0); ch < channels; ch++ { 2539 | if self.Allocation[ch][sb] != nil { 2540 | self.Scale_factor_info[ch][sb] = uint8(int8(plm_buffer_read(self.Buffer, 2))) 2541 | } 2542 | } 2543 | if self.Mode == plm_audio_mode_mono { 2544 | self.Scale_factor_info[1][sb] = self.Scale_factor_info[0][sb] 2545 | } 2546 | } 2547 | for sb := int64(0); sb < sblimit; sb++ { 2548 | for ch := int64(0); ch < channels; ch++ { 2549 | if self.Allocation[ch][sb] != nil { 2550 | var sf *int64 = &self.Scale_factor[ch][sb][0] 2551 | switch self.Scale_factor_info[ch][sb] { 2552 | case 0: 2553 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*0)) = plm_buffer_read(self.Buffer, 6) 2554 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*1)) = plm_buffer_read(self.Buffer, 6) 2555 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*2)) = plm_buffer_read(self.Buffer, 6) 2556 | case 1: 2557 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*0)) = func() int64 { 2558 | p := (*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*1)) 2559 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*1)) = plm_buffer_read(self.Buffer, 6) 2560 | return *p 2561 | }() 2562 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*2)) = plm_buffer_read(self.Buffer, 6) 2563 | case 2: 2564 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*0)) = func() int64 { 2565 | p := (*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*1)) 2566 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*1)) = func() int64 { 2567 | p := (*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*2)) 2568 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*2)) = plm_buffer_read(self.Buffer, 6) 2569 | return *p 2570 | }() 2571 | return *p 2572 | }() 2573 | case 3: 2574 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*0)) = plm_buffer_read(self.Buffer, 6) 2575 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*1)) = func() int64 { 2576 | p := (*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*2)) 2577 | *(*int64)(unsafe.Add(unsafe.Pointer(sf), unsafe.Sizeof(int64(0))*2)) = plm_buffer_read(self.Buffer, 6) 2578 | return *p 2579 | }() 2580 | } 2581 | } 2582 | } 2583 | if self.Mode == plm_audio_mode_mono { 2584 | self.Scale_factor[1][sb][0] = self.Scale_factor[0][sb][0] 2585 | self.Scale_factor[1][sb][1] = self.Scale_factor[0][sb][1] 2586 | self.Scale_factor[1][sb][2] = self.Scale_factor[0][sb][2] 2587 | } 2588 | } 2589 | var out_pos int64 = 0 2590 | for part := int64(0); part < 3; part++ { 2591 | for granule := int64(0); granule < 4; granule++ { 2592 | for sb := int64(0); sb < self.Bound; sb++ { 2593 | plm_audio_read_samples(self, 0, sb, part) 2594 | plm_audio_read_samples(self, 1, sb, part) 2595 | } 2596 | for sb := int64(self.Bound); sb < sblimit; sb++ { 2597 | plm_audio_read_samples(self, 0, sb, part) 2598 | self.Sample[1][sb][0] = self.Sample[0][sb][0] 2599 | self.Sample[1][sb][1] = self.Sample[0][sb][1] 2600 | self.Sample[1][sb][2] = self.Sample[0][sb][2] 2601 | } 2602 | for sb := int64(sblimit); sb < 32; sb++ { 2603 | self.Sample[0][sb][0] = 0 2604 | self.Sample[0][sb][1] = 0 2605 | self.Sample[0][sb][2] = 0 2606 | self.Sample[1][sb][0] = 0 2607 | self.Sample[1][sb][1] = 0 2608 | self.Sample[1][sb][2] = 0 2609 | } 2610 | for p := int64(0); p < 3; p++ { 2611 | self.V_pos = (self.V_pos - 64) & 1023 2612 | for ch := int64(0); ch < 2; ch++ { 2613 | plm_audio_idct36(self.Sample[ch], p, &self.V[ch][0], self.V_pos) 2614 | *(*[32]float32)(unsafe.Pointer(&self.U[0])) = [32]float32{} 2615 | var d_index int64 = 512 - (self.V_pos >> 1) 2616 | var v_index int64 = (self.V_pos % 128) >> 1 2617 | for v_index < 1024 { 2618 | for i := int64(0); i < 32; i++ { 2619 | self.U[i] += self.D[func() int64 { 2620 | p := &d_index 2621 | x := *p 2622 | *p++ 2623 | return x 2624 | }()] * self.V[ch][func() int64 { 2625 | p := &v_index 2626 | x := *p 2627 | *p++ 2628 | return x 2629 | }()] 2630 | } 2631 | v_index += 128 - 32 2632 | d_index += 64 - 32 2633 | } 2634 | d_index -= 512 - 32 2635 | v_index = (128 - 32 + 1024) - v_index 2636 | for v_index < 1024 { 2637 | for i := int64(0); i < 32; i++ { 2638 | self.U[i] += self.D[func() int64 { 2639 | p := &d_index 2640 | x := *p 2641 | *p++ 2642 | return x 2643 | }()] * self.V[ch][func() int64 { 2644 | p := &v_index 2645 | x := *p 2646 | *p++ 2647 | return x 2648 | }()] 2649 | } 2650 | v_index += 128 - 32 2651 | d_index += 64 - 32 2652 | } 2653 | for j := int64(0); j < 32; j++ { 2654 | self.Samples.Interleaved[((out_pos+j)<<1)+ch] = float32(float64(self.U[j]) / 2.147418112e+09) 2655 | } 2656 | } 2657 | out_pos += 32 2658 | } 2659 | } 2660 | } 2661 | plm_buffer_align(self.Buffer) 2662 | } 2663 | func plm_audio_read_allocation(self *plm_audio_t, sb int64, tab3 int64) *plm_quantizer_spec_t { 2664 | var ( 2665 | tab4 int64 = int64(plm_audio_quant_lut_step_3[tab3][sb]) 2666 | qtab int64 = int64(plm_audio_quant_lut_step_4[tab4&15][plm_buffer_read(self.Buffer, tab4>>4)]) 2667 | ) 2668 | if qtab != 0 { 2669 | return &plm_audio_quant_tab[qtab-1] 2670 | } 2671 | return nil 2672 | } 2673 | func plm_audio_read_samples(self *plm_audio_t, ch int64, sb int64, part int64) { 2674 | var ( 2675 | q *plm_quantizer_spec_t = self.Allocation[ch][sb] 2676 | sf int64 = self.Scale_factor[ch][sb][part] 2677 | sample *int64 = &self.Sample[ch][sb][0] 2678 | val int64 = 0 2679 | ) 2680 | if q == nil { 2681 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*0)) = func() int64 { 2682 | p := (*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*1)) 2683 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*1)) = func() int64 { 2684 | p := (*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*2)) 2685 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*2)) = 0 2686 | return *p 2687 | }() 2688 | return *p 2689 | }() 2690 | return 2691 | } 2692 | if sf == 63 { 2693 | sf = 0 2694 | } else { 2695 | var shift int64 = (sf / 3) | 0 2696 | sf = (plm_audio_scalefactor_base[sf%3] + ((1 << shift) >> 1)) >> shift 2697 | } 2698 | var adj int64 = int64(q.Levels) 2699 | if int64(q.Group) != 0 { 2700 | val = plm_buffer_read(self.Buffer, int64(q.Bits)) 2701 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*0)) = val % adj 2702 | val /= adj 2703 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*1)) = val % adj 2704 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*2)) = val / adj 2705 | } else { 2706 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*0)) = plm_buffer_read(self.Buffer, int64(q.Bits)) 2707 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*1)) = plm_buffer_read(self.Buffer, int64(q.Bits)) 2708 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*2)) = plm_buffer_read(self.Buffer, int64(q.Bits)) 2709 | } 2710 | var scale int64 = 0x10000 / (adj + 1) 2711 | adj = ((adj + 1) >> 1) - 1 2712 | val = (adj - *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*0))) * scale 2713 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*0)) = (val*(sf>>12) + ((val*(sf&4095) + 2048) >> 12)) >> 12 2714 | val = (adj - *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*1))) * scale 2715 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*1)) = (val*(sf>>12) + ((val*(sf&4095) + 2048) >> 12)) >> 12 2716 | val = (adj - *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*2))) * scale 2717 | *(*int64)(unsafe.Add(unsafe.Pointer(sample), unsafe.Sizeof(int64(0))*2)) = (val*(sf>>12) + ((val*(sf&4095) + 2048) >> 12)) >> 12 2718 | } 2719 | func plm_audio_idct36(s [32][3]int64, ss int64, d *float32, dp int64) { 2720 | var ( 2721 | t01 float32 2722 | t02 float32 2723 | t03 float32 2724 | t04 float32 2725 | t05 float32 2726 | t06 float32 2727 | t07 float32 2728 | t08 float32 2729 | t09 float32 2730 | t10 float32 2731 | t11 float32 2732 | t12 float32 2733 | t13 float32 2734 | t14 float32 2735 | t15 float32 2736 | t16 float32 2737 | t17 float32 2738 | t18 float32 2739 | t19 float32 2740 | t20 float32 2741 | t21 float32 2742 | t22 float32 2743 | t23 float32 2744 | t24 float32 2745 | t25 float32 2746 | t26 float32 2747 | t27 float32 2748 | t28 float32 2749 | t29 float32 2750 | t30 float32 2751 | t31 float32 2752 | t32 float32 2753 | t33 float32 2754 | ) 2755 | t01 = float32(s[0][ss] + s[31][ss]) 2756 | t02 = float32(float64(float32(s[0][ss]-s[31][ss])) * 0.500602998235) 2757 | t03 = float32(s[1][ss] + s[30][ss]) 2758 | t04 = float32(float64(float32(s[1][ss]-s[30][ss])) * 0.505470959898) 2759 | t05 = float32(s[2][ss] + s[29][ss]) 2760 | t06 = float32(float64(float32(s[2][ss]-s[29][ss])) * 0.515447309923) 2761 | t07 = float32(s[3][ss] + s[28][ss]) 2762 | t08 = float32(float64(float32(s[3][ss]-s[28][ss])) * 0.53104259109) 2763 | t09 = float32(s[4][ss] + s[27][ss]) 2764 | t10 = float32(float64(float32(s[4][ss]-s[27][ss])) * 0.553103896034) 2765 | t11 = float32(s[5][ss] + s[26][ss]) 2766 | t12 = float32(float64(float32(s[5][ss]-s[26][ss])) * 0.582934968206) 2767 | t13 = float32(s[6][ss] + s[25][ss]) 2768 | t14 = float32(float64(float32(s[6][ss]-s[25][ss])) * 0.622504123036) 2769 | t15 = float32(s[7][ss] + s[24][ss]) 2770 | t16 = float32(float64(float32(s[7][ss]-s[24][ss])) * 0.674808341455) 2771 | t17 = float32(s[8][ss] + s[23][ss]) 2772 | t18 = float32(float64(float32(s[8][ss]-s[23][ss])) * 0.744536271002) 2773 | t19 = float32(s[9][ss] + s[22][ss]) 2774 | t20 = float32(float64(float32(s[9][ss]-s[22][ss])) * 0.839349645416) 2775 | t21 = float32(s[10][ss] + s[21][ss]) 2776 | t22 = float32(float64(float32(s[10][ss]-s[21][ss])) * 0.972568237862) 2777 | t23 = float32(s[11][ss] + s[20][ss]) 2778 | t24 = float32(float64(float32(s[11][ss]-s[20][ss])) * 1.16943993343) 2779 | t25 = float32(s[12][ss] + s[19][ss]) 2780 | t26 = float32(float64(float32(s[12][ss]-s[19][ss])) * 1.48416461631) 2781 | t27 = float32(s[13][ss] + s[18][ss]) 2782 | t28 = float32(float64(float32(s[13][ss]-s[18][ss])) * 2.05778100995) 2783 | t29 = float32(s[14][ss] + s[17][ss]) 2784 | t30 = float32(float64(float32(s[14][ss]-s[17][ss])) * 3.40760841847) 2785 | t31 = float32(s[15][ss] + s[16][ss]) 2786 | t32 = float32(float64(float32(s[15][ss]-s[16][ss])) * 10.1900081235) 2787 | t33 = t01 + t31 2788 | t31 = float32(float64(t01-t31) * 0.502419286188) 2789 | t01 = t03 + t29 2790 | t29 = float32(float64(t03-t29) * 0.52249861494) 2791 | t03 = t05 + t27 2792 | t27 = float32(float64(t05-t27) * 0.566944034816) 2793 | t05 = t07 + t25 2794 | t25 = float32(float64(t07-t25) * 0.64682178336) 2795 | t07 = t09 + t23 2796 | t23 = float32(float64(t09-t23) * 0.788154623451) 2797 | t09 = t11 + t21 2798 | t21 = float32(float64(t11-t21) * 1.06067768599) 2799 | t11 = t13 + t19 2800 | t19 = float32(float64(t13-t19) * 1.72244709824) 2801 | t13 = t15 + t17 2802 | t17 = float32(float64(t15-t17) * 5.10114861869) 2803 | t15 = t33 + t13 2804 | t13 = float32(float64(t33-t13) * 0.509795579104) 2805 | t33 = t01 + t11 2806 | t01 = float32(float64(t01-t11) * 0.601344886935) 2807 | t11 = t03 + t09 2808 | t09 = float32(float64(t03-t09) * 0.899976223136) 2809 | t03 = t05 + t07 2810 | t07 = float32(float64(t05-t07) * 2.56291544774) 2811 | t05 = t15 + t03 2812 | t15 = float32(float64(t15-t03) * 0.541196100146) 2813 | t03 = t33 + t11 2814 | t11 = float32(float64(t33-t11) * 1.30656296488) 2815 | t33 = t05 + t03 2816 | t05 = float32(float64(t05-t03) * 0.707106781187) 2817 | t03 = t15 + t11 2818 | t15 = float32(float64(t15-t11) * 0.707106781187) 2819 | t03 += t15 2820 | t11 = t13 + t07 2821 | t13 = float32(float64(t13-t07) * 0.541196100146) 2822 | t07 = t01 + t09 2823 | t09 = float32(float64(t01-t09) * 1.30656296488) 2824 | t01 = t11 + t07 2825 | t07 = float32(float64(t11-t07) * 0.707106781187) 2826 | t11 = t13 + t09 2827 | t13 = float32(float64(t13-t09) * 0.707106781187) 2828 | t11 += t13 2829 | t01 += t11 2830 | t11 += t07 2831 | t07 += t13 2832 | t09 = t31 + t17 2833 | t31 = float32(float64(t31-t17) * 0.509795579104) 2834 | t17 = t29 + t19 2835 | t29 = float32(float64(t29-t19) * 0.601344886935) 2836 | t19 = t27 + t21 2837 | t21 = float32(float64(t27-t21) * 0.899976223136) 2838 | t27 = t25 + t23 2839 | t23 = float32(float64(t25-t23) * 2.56291544774) 2840 | t25 = t09 + t27 2841 | t09 = float32(float64(t09-t27) * 0.541196100146) 2842 | t27 = t17 + t19 2843 | t19 = float32(float64(t17-t19) * 1.30656296488) 2844 | t17 = t25 + t27 2845 | t27 = float32(float64(t25-t27) * 0.707106781187) 2846 | t25 = t09 + t19 2847 | t19 = float32(float64(t09-t19) * 0.707106781187) 2848 | t25 += t19 2849 | t09 = t31 + t23 2850 | t31 = float32(float64(t31-t23) * 0.541196100146) 2851 | t23 = t29 + t21 2852 | t21 = float32(float64(t29-t21) * 1.30656296488) 2853 | t29 = t09 + t23 2854 | t23 = float32(float64(t09-t23) * 0.707106781187) 2855 | t09 = t31 + t21 2856 | t31 = float32(float64(t31-t21) * 0.707106781187) 2857 | t09 += t31 2858 | t29 += t09 2859 | t09 += t23 2860 | t23 += t31 2861 | t17 += t29 2862 | t29 += t25 2863 | t25 += t09 2864 | t09 += t27 2865 | t27 += t23 2866 | t23 += t19 2867 | t19 += t31 2868 | t21 = t02 + t32 2869 | t02 = float32(float64(t02-t32) * 0.502419286188) 2870 | t32 = t04 + t30 2871 | t04 = float32(float64(t04-t30) * 0.52249861494) 2872 | t30 = t06 + t28 2873 | t28 = float32(float64(t06-t28) * 0.566944034816) 2874 | t06 = t08 + t26 2875 | t08 = float32(float64(t08-t26) * 0.64682178336) 2876 | t26 = t10 + t24 2877 | t10 = float32(float64(t10-t24) * 0.788154623451) 2878 | t24 = t12 + t22 2879 | t22 = float32(float64(t12-t22) * 1.06067768599) 2880 | t12 = t14 + t20 2881 | t20 = float32(float64(t14-t20) * 1.72244709824) 2882 | t14 = t16 + t18 2883 | t16 = float32(float64(t16-t18) * 5.10114861869) 2884 | t18 = t21 + t14 2885 | t14 = float32(float64(t21-t14) * 0.509795579104) 2886 | t21 = t32 + t12 2887 | t32 = float32(float64(t32-t12) * 0.601344886935) 2888 | t12 = t30 + t24 2889 | t24 = float32(float64(t30-t24) * 0.899976223136) 2890 | t30 = t06 + t26 2891 | t26 = float32(float64(t06-t26) * 2.56291544774) 2892 | t06 = t18 + t30 2893 | t18 = float32(float64(t18-t30) * 0.541196100146) 2894 | t30 = t21 + t12 2895 | t12 = float32(float64(t21-t12) * 1.30656296488) 2896 | t21 = t06 + t30 2897 | t30 = float32(float64(t06-t30) * 0.707106781187) 2898 | t06 = t18 + t12 2899 | t12 = float32(float64(t18-t12) * 0.707106781187) 2900 | t06 += t12 2901 | t18 = t14 + t26 2902 | t26 = float32(float64(t14-t26) * 0.541196100146) 2903 | t14 = t32 + t24 2904 | t24 = float32(float64(t32-t24) * 1.30656296488) 2905 | t32 = t18 + t14 2906 | t14 = float32(float64(t18-t14) * 0.707106781187) 2907 | t18 = t26 + t24 2908 | t24 = float32(float64(t26-t24) * 0.707106781187) 2909 | t18 += t24 2910 | t32 += t18 2911 | t18 += t14 2912 | t26 = t14 + t24 2913 | t14 = t02 + t16 2914 | t02 = float32(float64(t02-t16) * 0.509795579104) 2915 | t16 = t04 + t20 2916 | t04 = float32(float64(t04-t20) * 0.601344886935) 2917 | t20 = t28 + t22 2918 | t22 = float32(float64(t28-t22) * 0.899976223136) 2919 | t28 = t08 + t10 2920 | t10 = float32(float64(t08-t10) * 2.56291544774) 2921 | t08 = t14 + t28 2922 | t14 = float32(float64(t14-t28) * 0.541196100146) 2923 | t28 = t16 + t20 2924 | t20 = float32(float64(t16-t20) * 1.30656296488) 2925 | t16 = t08 + t28 2926 | t28 = float32(float64(t08-t28) * 0.707106781187) 2927 | t08 = t14 + t20 2928 | t20 = float32(float64(t14-t20) * 0.707106781187) 2929 | t08 += t20 2930 | t14 = t02 + t10 2931 | t02 = float32(float64(t02-t10) * 0.541196100146) 2932 | t10 = t04 + t22 2933 | t22 = float32(float64(t04-t22) * 1.30656296488) 2934 | t04 = t14 + t10 2935 | t10 = float32(float64(t14-t10) * 0.707106781187) 2936 | t14 = t02 + t22 2937 | t02 = float32(float64(t02-t22) * 0.707106781187) 2938 | t14 += t02 2939 | t04 += t14 2940 | t14 += t10 2941 | t10 += t02 2942 | t16 += t04 2943 | t04 += t08 2944 | t08 += t14 2945 | t14 += t28 2946 | t28 += t10 2947 | t10 += t20 2948 | t20 += t02 2949 | t21 += t16 2950 | t16 += t32 2951 | t32 += t04 2952 | t04 += t06 2953 | t06 += t08 2954 | t08 += t18 2955 | t18 += t14 2956 | t14 += t30 2957 | t30 += t28 2958 | t28 += t26 2959 | t26 += t10 2960 | t10 += t12 2961 | t12 += t20 2962 | t20 += t24 2963 | t24 += t02 2964 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+48))) = -t33 2965 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+49))) = func() float32 { 2966 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+47))) 2967 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+47))) = -t21 2968 | return *p 2969 | }() 2970 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+50))) = func() float32 { 2971 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+46))) 2972 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+46))) = -t17 2973 | return *p 2974 | }() 2975 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+51))) = func() float32 { 2976 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+45))) 2977 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+45))) = -t16 2978 | return *p 2979 | }() 2980 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+52))) = func() float32 { 2981 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+44))) 2982 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+44))) = -t01 2983 | return *p 2984 | }() 2985 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+53))) = func() float32 { 2986 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+43))) 2987 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+43))) = -t32 2988 | return *p 2989 | }() 2990 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+54))) = func() float32 { 2991 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+42))) 2992 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+42))) = -t29 2993 | return *p 2994 | }() 2995 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+55))) = func() float32 { 2996 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+41))) 2997 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+41))) = -t04 2998 | return *p 2999 | }() 3000 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+56))) = func() float32 { 3001 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+40))) 3002 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+40))) = -t03 3003 | return *p 3004 | }() 3005 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+57))) = func() float32 { 3006 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+39))) 3007 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+39))) = -t06 3008 | return *p 3009 | }() 3010 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+58))) = func() float32 { 3011 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+38))) 3012 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+38))) = -t25 3013 | return *p 3014 | }() 3015 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+59))) = func() float32 { 3016 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+37))) 3017 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+37))) = -t08 3018 | return *p 3019 | }() 3020 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+60))) = func() float32 { 3021 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+36))) 3022 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+36))) = -t11 3023 | return *p 3024 | }() 3025 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+61))) = func() float32 { 3026 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+35))) 3027 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+35))) = -t18 3028 | return *p 3029 | }() 3030 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+62))) = func() float32 { 3031 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+34))) 3032 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+34))) = -t09 3033 | return *p 3034 | }() 3035 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+63))) = func() float32 { 3036 | p := (*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+33))) 3037 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+33))) = -t14 3038 | return *p 3039 | }() 3040 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+32))) = -t05 3041 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+0))) = t05 3042 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+31))) = -t30 3043 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+1))) = t30 3044 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+30))) = -t27 3045 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+2))) = t27 3046 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+29))) = -t28 3047 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+3))) = t28 3048 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+28))) = -t07 3049 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+4))) = t07 3050 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+27))) = -t26 3051 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+5))) = t26 3052 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+26))) = -t23 3053 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+6))) = t23 3054 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+25))) = -t10 3055 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+7))) = t10 3056 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+24))) = -t15 3057 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+8))) = t15 3058 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+23))) = -t12 3059 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+9))) = t12 3060 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+22))) = -t19 3061 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+10))) = t19 3062 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+21))) = -t20 3063 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+11))) = t20 3064 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+20))) = -t13 3065 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+12))) = t13 3066 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+19))) = -t24 3067 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+13))) = t24 3068 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+18))) = -t31 3069 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+14))) = t31 3070 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+17))) = -t02 3071 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+15))) = t02 3072 | *(*float32)(unsafe.Add(unsafe.Pointer(d), unsafe.Sizeof(float32(0))*uintptr(dp+16))) = 0.0 3073 | } 3074 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package mpg 2 | 3 | import ( 4 | "time" 5 | "unsafe" 6 | ) 7 | 8 | func index(data *uint8, i int) byte { 9 | ptr := unsafe.Add(unsafe.Pointer(data), unsafe.Sizeof(uint8(0))*uintptr(i)) 10 | return *(*byte)(ptr) 11 | } 12 | 13 | func bytesToUintPtr(data []byte) *uint8 { 14 | return (*uint8)(unsafe.Pointer(&data[0])) 15 | } 16 | 17 | func boolToInt(t bool) int64 { 18 | if t { 19 | return _true 20 | } else { 21 | return _false 22 | } 23 | } 24 | 25 | func floatToSecs(t float64) time.Duration { 26 | return time.Duration(t * float64(time.Second)) 27 | } 28 | 29 | // SetAlpha is a helper function intended to set the alpha channel of 30 | // "*image.RGBA.Pix" byte array since functions like "ReadRGBA" and "ReadRGBAAt" 31 | // does not set alpha. 32 | func SetAlpha(a byte, data []byte) { 33 | for i := 3; i < len(data); i += 4 { 34 | data[i] = a 35 | } 36 | } 37 | --------------------------------------------------------------------------------