RIT VEXU Core API
Loading...
Searching...
No Matches
pl_mpeg.h
1#include "vex.h"
2/*
3PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer
4
5Dominic Szablewski - https://phoboslab.org
6
7
8-- LICENSE: The MIT License(MIT)
9
10Copyright(c) 2019 Dominic Szablewski
11
12Permission is hereby granted, free of charge, to any person obtaining a copy of
13this software and associated documentation files(the "Software"), to deal in
14the Software without restriction, including without limitation the rights to
15use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies
16of the Software, and to permit persons to whom the Software is furnished to do
17so, subject to the following conditions :
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27
28
29
30
31-- Synopsis
32
33// Define `PL_MPEG_IMPLEMENTATION` in *one* C/C++ file before including this
34// library to create the implementation.
35
36#define PL_MPEG_IMPLEMENTATION
37#include "plmpeg.h"
38
39// This function gets called for each decoded video frame
40void my_video_callback(plm_t *plm, plm_frame_t *frame, void *user) {
41 // Do something with frame->y.data, frame->cr.data, frame->cb.data
42}
43
44// This function gets called for each decoded audio frame
45void my_audio_callback(plm_t *plm, plm_samples_t *frame, void *user) {
46 // Do something with samples->interleaved
47}
48
49// Load a .mpg (MPEG Program Stream) file
50plm_t *plm = plm_create_with_filename("some-file.mpg");
51
52// Install the video & audio decode callbacks
53plm_set_video_decode_callback(plm, my_video_callback, my_data);
54plm_set_audio_decode_callback(plm, my_audio_callback, my_data);
55
56
57// Decode
58do {
59 plm_decode(plm, time_since_last_call);
60} while (!plm_has_ended(plm));
61
62// All done
63plm_destroy(plm);
64
65
66
67-- Documentation
68
69This library provides several interfaces to load, demux and decode MPEG video
70and audio data. A high-level API combines the demuxer, video & audio decoders
71in an easy to use wrapper.
72
73Lower-level APIs for accessing the demuxer, video decoder and audio decoder,
74as well as providing different data sources are also available.
75
76Interfaces are written in an object oriented style, meaning you create object
77instances via various different constructor functions (plm_*create()),
78do some work on them and later dispose them via plm_*destroy().
79
80plm_* ......... the high-level interface, combining demuxer and decoders
81plm_buffer_* .. the data source used by all interfaces
82plm_demux_* ... the MPEG-PS demuxer
83plm_video_* ... the MPEG1 Video ("mpeg1") decoder
84plm_audio_* ... the MPEG1 Audio Layer II ("mp2") decoder
85
86
87With the high-level interface you have two options to decode video & audio:
88
89 1. Use plm_decode() and just hand over the delta time since the last call.
90 It will decode everything needed and call your callbacks (specified through
91 plm_set_{video|audio}_decode_callback()) any number of times.
92
93 2. Use plm_decode_video() and plm_decode_audio() to decode exactly one
94 frame of video or audio data at a time. How you handle the synchronization
95 of both streams is up to you.
96
97If you only want to decode video *or* audio through these functions, you should
98disable the other stream (plm_set_{video|audio}_enabled(FALSE))
99
100Video data is decoded into a struct with all 3 planes (Y, Cr, Cb) stored in
101separate buffers. You can either convert this to RGB on the CPU (slow) via the
102plm_frame_to_rgb() function or do it on the GPU with the following matrix:
103
104mat4 bt601 = mat4(
105 1.16438, 0.00000, 1.59603, -0.87079,
106 1.16438, -0.39176, -0.81297, 0.52959,
107 1.16438, 2.01723, 0.00000, -1.08139,
108 0, 0, 0, 1
109);
110gl_FragColor = vec4(y, cb, cr, 1.0) * bt601;
111
112Audio data is decoded into a struct with either one single float array with the
113samples for the left and right channel interleaved, or if the
114PLM_AUDIO_SEPARATE_CHANNELS is defined *before* including this library, into
115two separate float arrays - one for each channel.
116
117
118Data can be supplied to the high level interface, the demuxer and the decoders
119in three different ways:
120
121 1. Using plm_create_from_filename() or with a file handle with
122 plm_create_from_file().
123
124 2. Using plm_create_with_memory() and supplying a pointer to memory that
125 contains the whole file.
126
127 3. Using plm_create_with_buffer(), supplying your own plm_buffer_t instance and
128 periodically writing to this buffer.
129
130When using your own plm_buffer_t instance, you can fill this buffer using
131plm_buffer_write(). You can either monitor plm_buffer_get_remaining() and push
132data when appropriate, or install a callback on the buffer with
133plm_buffer_set_load_callback() that gets called whenever the buffer needs more
134data.
135
136A buffer created with plm_buffer_create_with_capacity() is treated as a ring
137buffer, meaning that data that has already been read, will be discarded. In
138contrast, a buffer created with plm_buffer_create_for_appending() will keep all
139data written to it in memory. This enables seeking in the already loaded data.
140
141
142There should be no need to use the lower level plm_demux_*, plm_video_* and
143plm_audio_* functions, if all you want to do is read/decode an MPEG-PS file.
144However, if you get raw mpeg1video data or raw mp2 audio data from a different
145source, these functions can be used to decode the raw data directly. Similarly,
146if you only want to analyze an MPEG-PS file or extract raw video or audio
147packets from it, you can use the plm_demux_* functions.
148
149
150This library uses malloc(), realloc() and free() to manage memory. Typically
151all allocation happens up-front when creating the interface. However, the
152default buffer size may be too small for certain inputs. In these cases plmpeg
153will realloc() the buffer with a larger size whenever needed. You can configure
154the default buffer size by defining PLM_BUFFER_DEFAULT_SIZE *before*
155including this library.
156
157You can also define PLM_MALLOC, PLM_REALLOC and PLM_FREE to provide your own
158memory management functions.
159
160
161See below for detailed the API documentation.
162
163*/
164
165#ifndef PL_MPEG_H
166#define PL_MPEG_H
167
168#include <stdint.h>
169// #include <stdio.h>
170
171#ifdef __cplusplus
172extern "C" {
173#endif
174
175// -----------------------------------------------------------------------------
176// Public Data Types
177
178// Object types for the various interfaces
179
180typedef struct plm_t plm_t;
181typedef struct plm_buffer_t plm_buffer_t;
182typedef struct plm_demux_t plm_demux_t;
183typedef struct plm_video_t plm_video_t;
184typedef struct plm_audio_t plm_audio_t;
185
186// Demuxed MPEG PS packet
187// The type maps directly to the various MPEG-PES start codes. PTS is the
188// presentation time stamp of the packet in seconds. Note that not all packets
189// have a PTS value, indicated by PLM_PACKET_INVALID_TS.
190
191#define PLM_PACKET_INVALID_TS -1
192
193typedef struct {
194 int type;
195 double pts;
196 size_t length;
197 uint8_t *data;
198} plm_packet_t;
199
200// Decoded Video Plane
201// The byte length of the data is width * height. Note that different planes
202// have different sizes: the Luma plane (Y) is double the size of each of
203// the two Chroma planes (Cr, Cb) - i.e. 4 times the byte length.
204// Also note that the size of the plane does *not* denote the size of the
205// displayed frame. The sizes of planes are always rounded up to the nearest
206// macroblock (16px).
207
208typedef struct {
209 unsigned int width;
210 unsigned int height;
211 uint8_t *data;
212} plm_plane_t;
213
214// Decoded Video Frame
215// width and height denote the desired display size of the frame. This may be
216// different from the internal size of the 3 planes.
217
218typedef struct {
219 double time;
220 unsigned int width;
221 unsigned int height;
222 plm_plane_t y;
223 plm_plane_t cr;
224 plm_plane_t cb;
225} plm_frame_t;
226
227// Callback function type for decoded video frames used by the high-level
228// plm_* interface
229
230typedef void (*plm_video_decode_callback)(plm_t *self, plm_frame_t *frame, void *user);
231
232// Decoded Audio Samples
233// Samples are stored as normalized (-1, 1) float either interleaved, or if
234// PLM_AUDIO_SEPARATE_CHANNELS is defined, in two separate arrays.
235// The `count` is always PLM_AUDIO_SAMPLES_PER_FRAME and just there for
236// convenience.
237
238#define PLM_AUDIO_SAMPLES_PER_FRAME 1152
239
240typedef struct {
241 double time;
242 unsigned int count;
243#ifdef PLM_AUDIO_SEPARATE_CHANNELS
244 float left[PLM_AUDIO_SAMPLES_PER_FRAME];
245 float right[PLM_AUDIO_SAMPLES_PER_FRAME];
246#else
247 float interleaved[PLM_AUDIO_SAMPLES_PER_FRAME * 2];
248#endif
249} plm_samples_t;
250
251// Callback function type for decoded audio samples used by the high-level
252// plm_* interface
253
254typedef void (*plm_audio_decode_callback)(plm_t *self, plm_samples_t *samples, void *user);
255
256// Callback function for plm_buffer when it needs more data
257
258typedef void (*plm_buffer_load_callback)(plm_buffer_t *self, void *user);
259
260// -----------------------------------------------------------------------------
261// plm_* public API
262// High-Level API for loading/demuxing/decoding MPEG-PS data
263
264// Create a plmpeg instance with a filename. Returns NULL if the file could not
265// be opened.
266
267plm_t *plm_create_with_filename(const char *filename);
268
269// Create a plmpeg instance with a file handle. Pass TRUE to close_when_done to
270// let plmpeg call fclose() on the handle when plm_destroy() is called.
271
272plm_t *plm_create_with_file(FIL *fh, int close_when_done);
273
274// Create a plmpeg instance with a pointer to memory as source. This assumes the
275// whole file is in memory. The memory is not copied. Pass TRUE to
276// free_when_done to let plmpeg call free() on the pointer when plm_destroy()
277// is called.
278
279plm_t *plm_create_with_memory(uint8_t *bytes, size_t length, int free_when_done);
280
281// Create a plmpeg instance with a plm_buffer as source. Pass TRUE to
282// destroy_when_done to let plmpeg call plm_buffer_destroy() on the buffer when
283// plm_destroy() is called.
284
285plm_t *plm_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done);
286
287// Destroy a plmpeg instance and free all data.
288
289void plm_destroy(plm_t *self);
290
291// Get whether we have headers on all available streams and we can accurately
292// report the number of video/audio streams, video dimensions, framerate and
293// audio samplerate.
294// This returns FALSE if the file is not an MPEG-PS file or - when not using a
295// file as source - when not enough data is available yet.
296
297int plm_has_headers(plm_t *self);
298
299// Get or set whether video decoding is enabled. Default TRUE.
300
301int plm_get_video_enabled(plm_t *self);
302void plm_set_video_enabled(plm_t *self, int enabled);
303
304// Get the number of video streams (0--1) reported in the system header.
305
306int plm_get_num_video_streams(plm_t *self);
307
308// Get the display width/height of the video stream.
309
310int plm_get_width(plm_t *self);
311int plm_get_height(plm_t *self);
312
313// Get the framerate of the video stream in frames per second.
314
315double plm_get_framerate(plm_t *self);
316
317// Get or set whether audio decoding is enabled. Default TRUE.
318
319int plm_get_audio_enabled(plm_t *self);
320void plm_set_audio_enabled(plm_t *self, int enabled);
321
322// Get the number of audio streams (0--4) reported in the system header.
323
324int plm_get_num_audio_streams(plm_t *self);
325
326// Set the desired audio stream (0--3). Default 0.
327
328void plm_set_audio_stream(plm_t *self, int stream_index);
329
330// Get the samplerate of the audio stream in samples per second.
331
332int plm_get_samplerate(plm_t *self);
333
334// Get or set the audio lead time in seconds - the time in which audio samples
335// are decoded in advance (or behind) the video decode time. Typically this
336// should be set to the duration of the buffer of the audio API that you use
337// for output. E.g. for SDL2: (SDL_AudioSpec.samples / samplerate)
338
339double plm_get_audio_lead_time(plm_t *self);
340void plm_set_audio_lead_time(plm_t *self, double lead_time);
341
342// Get the current internal time in seconds.
343
344double plm_get_time(plm_t *self);
345
346// Get the video duration of the underlying source in seconds.
347
348double plm_get_duration(plm_t *self);
349
350// Rewind all buffers back to the beginning.
351
352void plm_rewind(plm_t *self);
353
354// Get or set looping. Default FALSE.
355
356int plm_get_loop(plm_t *self);
357void plm_set_loop(plm_t *self, int loop);
358
359// Get whether the file has ended. If looping is enabled, this will always
360// return FALSE.
361
362int plm_has_ended(plm_t *self);
363
364// Set the callback for decoded video frames used with plm_decode(). If no
365// callback is set, video data will be ignored and not be decoded. The *user
366// Parameter will be passed to your callback.
367
368void plm_set_video_decode_callback(plm_t *self, plm_video_decode_callback fp, void *user);
369
370// Set the callback for decoded audio samples used with plm_decode(). If no
371// callback is set, audio data will be ignored and not be decoded. The *user
372// Parameter will be passed to your callback.
373
374void plm_set_audio_decode_callback(plm_t *self, plm_audio_decode_callback fp, void *user);
375
376// Advance the internal timer by seconds and decode video/audio up to this time.
377// This will call the video_decode_callback and audio_decode_callback any number
378// of times. A frame-skip is not implemented, i.e. everything up to current time
379// will be decoded.
380
381void plm_decode(plm_t *self, double seconds);
382
383// Decode and return one video frame. Returns NULL if no frame could be decoded
384// (either because the source ended or data is corrupt). If you only want to
385// decode video, you should disable audio via plm_set_audio_enabled().
386// The returned plm_frame_t is valid until the next call to plm_decode_video()
387// or until plm_destroy() is called.
388
389plm_frame_t *plm_decode_video(plm_t *self);
390
391// Decode and return one audio frame. Returns NULL if no frame could be decoded
392// (either because the source ended or data is corrupt). If you only want to
393// decode audio, you should disable video via plm_set_video_enabled().
394// The returned plm_samples_t is valid until the next call to plm_decode_audio()
395// or until plm_destroy() is called.
396
397plm_samples_t *plm_decode_audio(plm_t *self);
398
399// Seek to the specified time, clamped between 0 -- duration. This can only be
400// used when the underlying plm_buffer is seekable, i.e. for files, fixed
401// memory buffers or _for_appending buffers.
402// If seek_exact is TRUE this will seek to the exact time, otherwise it will
403// seek to the last intra frame just before the desired time. Exact seeking can
404// be slow, because all frames up to the seeked one have to be decoded on top of
405// the previous intra frame.
406// If seeking succeeds, this function will call the video_decode_callback
407// exactly once with the target frame. If audio is enabled, it will also call
408// the audio_decode_callback any number of times, until the audio_lead_time is
409// satisfied.
410// Returns TRUE if seeking succeeded or FALSE if no frame could be found.
411
412int plm_seek(plm_t *self, double time, int seek_exact);
413
414// Similar to plm_seek(), but will not call the video_decode_callback,
415// audio_decode_callback or make any attempts to sync audio.
416// Returns the found frame or NULL if no frame could be found.
417
418plm_frame_t *plm_seek_frame(plm_t *self, double time, int seek_exact);
419
420// -----------------------------------------------------------------------------
421// plm_buffer public API
422// Provides the data source for all other plm_* interfaces
423
424// The default size for buffers created from files or by the high-level API
425
426#ifndef PLM_BUFFER_DEFAULT_SIZE
427#define PLM_BUFFER_DEFAULT_SIZE (128 * 1024)
428#endif
429
430// Create a buffer instance with a filename. Returns NULL if the file could not
431// be opened.
432
433plm_buffer_t *plm_buffer_create_with_filename(const char *filename);
434
435// Create a buffer instance with a file handle. Pass TRUE to close_when_done
436// to let plmpeg call fclose() on the handle when plm_destroy() is called.
437
438plm_buffer_t *plm_buffer_create_with_file(FIL *fh, int close_when_done);
439
440// Create a buffer instance with a pointer to memory as source. This assumes
441// the whole file is in memory. The bytes are not copied. Pass 1 to
442// free_when_done to let plmpeg call free() on the pointer when plm_destroy()
443// is called.
444
445plm_buffer_t *plm_buffer_create_with_memory(uint8_t *bytes, size_t length, int free_when_done);
446
447// Create an empty buffer with an initial capacity. The buffer will grow
448// as needed. Data that has already been read, will be discarded.
449
450plm_buffer_t *plm_buffer_create_with_capacity(size_t capacity);
451
452// Create an empty buffer with an initial capacity. The buffer will grow
453// as needed. Decoded data will *not* be discarded. This can be used when
454// loading a file over the network, without needing to throttle the download.
455// It also allows for seeking in the already loaded data.
456
457plm_buffer_t *plm_buffer_create_for_appending(size_t initial_capacity);
458
459// Destroy a buffer instance and free all data
460
461void plm_buffer_destroy(plm_buffer_t *self);
462
463// Copy data into the buffer. If the data to be written is larger than the
464// available space, the buffer will realloc() with a larger capacity.
465// Returns the number of bytes written. This will always be the same as the
466// passed in length, except when the buffer was created _with_memory() for
467// which _write() is forbidden.
468
469size_t plm_buffer_write(plm_buffer_t *self, uint8_t *bytes, size_t length);
470
471// Mark the current byte length as the end of this buffer and signal that no
472// more data is expected to be written to it. This function should be called
473// just after the last plm_buffer_write().
474// For _with_capacity buffers, this is cleared on a plm_buffer_rewind().
475
476void plm_buffer_signal_end(plm_buffer_t *self);
477
478// Set a callback that is called whenever the buffer needs more data
479
480void plm_buffer_set_load_callback(plm_buffer_t *self, plm_buffer_load_callback fp, void *user);
481
482// Rewind the buffer back to the beginning. When loading from a file handle,
483// this also seeks to the beginning of the file.
484
485void plm_buffer_rewind(plm_buffer_t *self);
486
487// Get the total size. For files, this returns the file size. For all other
488// types it returns the number of bytes currently in the buffer.
489
490size_t plm_buffer_get_size(plm_buffer_t *self);
491
492// Get the number of remaining (yet unread) bytes in the buffer. This can be
493// useful to throttle writing.
494
495size_t plm_buffer_get_remaining(plm_buffer_t *self);
496
497// Get whether the read position of the buffer is at the end and no more data
498// is expected.
499
500int plm_buffer_has_ended(plm_buffer_t *self);
501
502// -----------------------------------------------------------------------------
503// plm_demux public API
504// Demux an MPEG Program Stream (PS) data into separate packages
505
506// Various Packet Types
507
508static const int PLM_DEMUX_PACKET_PRIVATE = 0xBD;
509static const int PLM_DEMUX_PACKET_AUDIO_1 = 0xC0;
510static const int PLM_DEMUX_PACKET_AUDIO_2 = 0xC1;
511static const int PLM_DEMUX_PACKET_AUDIO_3 = 0xC2;
512static const int PLM_DEMUX_PACKET_AUDIO_4 = 0xC2;
513static const int PLM_DEMUX_PACKET_VIDEO_1 = 0xE0;
514
515// Create a demuxer with a plm_buffer as source. This will also attempt to read
516// the pack and system headers from the buffer.
517
518plm_demux_t *plm_demux_create(plm_buffer_t *buffer, int destroy_when_done);
519
520// Destroy a demuxer and free all data.
521
522void plm_demux_destroy(plm_demux_t *self);
523
524// Returns TRUE/FALSE whether pack and system headers have been found. This will
525// attempt to read the headers if non are present yet.
526
527int plm_demux_has_headers(plm_demux_t *self);
528
529// Returns the number of video streams found in the system header. This will
530// attempt to read the system header if non is present yet.
531
532int plm_demux_get_num_video_streams(plm_demux_t *self);
533
534// Returns the number of audio streams found in the system header. This will
535// attempt to read the system header if non is present yet.
536
537int plm_demux_get_num_audio_streams(plm_demux_t *self);
538
539// Rewind the internal buffer. See plm_buffer_rewind().
540
541void plm_demux_rewind(plm_demux_t *self);
542
543// Get whether the file has ended. This will be cleared on seeking or rewind.
544
545int plm_demux_has_ended(plm_demux_t *self);
546
547// Seek to a packet of the specified type with a PTS just before specified time.
548// If force_intra is TRUE, only packets containing an intra frame will be
549// considered - this only makes sense when the type is PLM_DEMUX_PACKET_VIDEO_1.
550// Note that the specified time is considered 0-based, regardless of the first
551// PTS in the data source.
552
553plm_packet_t *plm_demux_seek(plm_demux_t *self, double time, int type, int force_intra);
554
555// Get the PTS of the first packet of this type. Returns PLM_PACKET_INVALID_TS
556// if not packet of this packet type can be found.
557
558double plm_demux_get_start_time(plm_demux_t *self, int type);
559
560// Get the duration for the specified packet type - i.e. the span between the
561// the first PTS and the last PTS in the data source. This only makes sense when
562// the underlying data source is a file or fixed memory.
563
564double plm_demux_get_duration(plm_demux_t *self, int type);
565
566// Decode and return the next packet. The returned packet_t is valid until
567// the next call to plm_demux_decode() or until the demuxer is destroyed.
568
569plm_packet_t *plm_demux_decode(plm_demux_t *self);
570
571// -----------------------------------------------------------------------------
572// plm_video public API
573// Decode MPEG1 Video ("mpeg1") data into raw YCrCb frames
574
575// Create a video decoder with a plm_buffer as source.
576
577plm_video_t *plm_video_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done);
578
579// Destroy a video decoder and free all data.
580
581void plm_video_destroy(plm_video_t *self);
582
583// Get whether a sequence header was found and we can accurately report on
584// dimensions and framerate.
585
586int plm_video_has_header(plm_video_t *self);
587
588// Get the framerate in frames per second.
589
590double plm_video_get_framerate(plm_video_t *self);
591
592// Get the display width/height.
593
594int plm_video_get_width(plm_video_t *self);
595int plm_video_get_height(plm_video_t *self);
596
597// Set "no delay" mode. When enabled, the decoder assumes that the video does
598// *not* contain any B-Frames. This is useful for reducing lag when streaming.
599// The default is FALSE.
600
601void plm_video_set_no_delay(plm_video_t *self, int no_delay);
602
603// Get the current internal time in seconds.
604
605double plm_video_get_time(plm_video_t *self);
606
607// Set the current internal time in seconds. This is only useful when you
608// manipulate the underlying video buffer and want to enforce a correct
609// timestamps.
610
611void plm_video_set_time(plm_video_t *self, double time);
612
613// Rewind the internal buffer. See plm_buffer_rewind().
614
615void plm_video_rewind(plm_video_t *self);
616
617// Get whether the file has ended. This will be cleared on rewind.
618
619int plm_video_has_ended(plm_video_t *self);
620
621// Decode and return one frame of video and advance the internal time by
622// 1/framerate seconds. The returned frame_t is valid until the next call of
623// plm_video_decode() or until the video decoder is destroyed.
624
625plm_frame_t *plm_video_decode(plm_video_t *self);
626
627// Convert the YCrCb data of a frame into interleaved R G B data. The stride
628// specifies the width in bytes of the destination buffer. I.e. the number of
629// bytes from one line to the next. The stride must be at least
630// (frame->width * bytes_per_pixel). The buffer pointed to by *dest must have a
631// size of at least (stride * frame->height).
632// Note that the alpha component of the dest buffer is always left untouched.
633
634void plm_frame_to_rgb(plm_frame_t *frame, uint8_t *dest, int stride);
635void plm_frame_to_bgr(plm_frame_t *frame, uint8_t *dest, int stride);
636void plm_frame_to_rgba(plm_frame_t *frame, uint8_t *dest, int stride);
637void plm_frame_to_bgra(plm_frame_t *frame, uint8_t *dest, int stride);
638void plm_frame_to_argb(plm_frame_t *frame, uint8_t *dest, int stride);
639void plm_frame_to_abgr(plm_frame_t *frame, uint8_t *dest, int stride);
640
641// -----------------------------------------------------------------------------
642// plm_audio public API
643// Decode MPEG-1 Audio Layer II ("mp2") data into raw samples
644
645// Create an audio decoder with a plm_buffer as source.
646
647plm_audio_t *plm_audio_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done);
648
649// Destroy an audio decoder and free all data.
650
651void plm_audio_destroy(plm_audio_t *self);
652
653// Get whether a frame header was found and we can accurately report on
654// samplerate.
655
656int plm_audio_has_header(plm_audio_t *self);
657
658// Get the samplerate in samples per second.
659
660int plm_audio_get_samplerate(plm_audio_t *self);
661
662// Get the current internal time in seconds.
663
664double plm_audio_get_time(plm_audio_t *self);
665
666// Set the current internal time in seconds. This is only useful when you
667// manipulate the underlying video buffer and want to enforce a correct
668// timestamps.
669
670void plm_audio_set_time(plm_audio_t *self, double time);
671
672// Rewind the internal buffer. See plm_buffer_rewind().
673
674void plm_audio_rewind(plm_audio_t *self);
675
676// Get whether the file has ended. This will be cleared on rewind.
677
678int plm_audio_has_ended(plm_audio_t *self);
679
680// Decode and return one "frame" of audio and advance the internal time by
681// (PLM_AUDIO_SAMPLES_PER_FRAME/samplerate) seconds. The returned samples_t
682// is valid until the next call of plm_audio_decode() or until the audio
683// decoder is destroyed.
684
685plm_samples_t *plm_audio_decode(plm_audio_t *self);
686
687#ifdef __cplusplus
688}
689#endif
690
691#endif // PL_MPEG_H
692
693// -----------------------------------------------------------------------------
694// -----------------------------------------------------------------------------
695// IMPLEMENTATION
696
697#ifdef PL_MPEG_IMPLEMENTATION
698
699#include <stdlib.h>
700#include <string.h>
701
702#ifndef TRUE
703#define TRUE 1
704#define FALSE 0
705#endif
706
707#ifndef PLM_MALLOC
708#define PLM_MALLOC(sz) malloc(sz)
709#define PLM_FREE(p) free(p)
710#define PLM_REALLOC(p, sz) realloc(p, sz)
711#endif
712
713#define PLM_UNUSED(expr) (void)(expr)
714
715// -----------------------------------------------------------------------------
716// plm (high-level interface) implementation
717
718struct plm_t {
719 plm_demux_t *demux;
720 double time;
721 int has_ended;
722 int loop;
723 int has_decoders;
724
725 int video_enabled;
726 int video_packet_type;
727 plm_buffer_t *video_buffer;
728 plm_video_t *video_decoder;
729
730 int audio_enabled;
731 int audio_stream_index;
732 int audio_packet_type;
733 double audio_lead_time;
734 plm_buffer_t *audio_buffer;
735 plm_audio_t *audio_decoder;
736
737 plm_video_decode_callback video_decode_callback;
738 void *video_decode_callback_user_data;
739
740 plm_audio_decode_callback audio_decode_callback;
741 void *audio_decode_callback_user_data;
742};
743
744int plm_init_decoders(plm_t *self);
745void plm_handle_end(plm_t *self);
746void plm_read_video_packet(plm_buffer_t *buffer, void *user);
747void plm_read_audio_packet(plm_buffer_t *buffer, void *user);
748void plm_read_packets(plm_t *self, int requested_type);
749
750plm_t *plm_create_with_filename(const char *filename) {
751 plm_buffer_t *buffer = plm_buffer_create_with_filename(filename);
752 if (!buffer) {
753 return NULL;
754 }
755 return plm_create_with_buffer(buffer, TRUE);
756}
757
758plm_t *plm_create_with_file(FIL *fh, int close_when_done) {
759 plm_buffer_t *buffer = plm_buffer_create_with_file(fh, close_when_done);
760 return plm_create_with_buffer(buffer, TRUE);
761}
762
763plm_t *plm_create_with_memory(uint8_t *bytes, size_t length, int free_when_done) {
764 plm_buffer_t *buffer = plm_buffer_create_with_memory(bytes, length, free_when_done);
765 return plm_create_with_buffer(buffer, TRUE);
766}
767
768plm_t *plm_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done) {
769 plm_t *self = (plm_t *)PLM_MALLOC(sizeof(plm_t));
770 memset(self, 0, sizeof(plm_t));
771
772 self->demux = plm_demux_create(buffer, destroy_when_done);
773 self->video_enabled = TRUE;
774 self->audio_enabled = TRUE;
775 plm_init_decoders(self);
776
777 return self;
778}
779
780int plm_init_decoders(plm_t *self) {
781 if (self->has_decoders) {
782 return TRUE;
783 }
784
785 if (!plm_demux_has_headers(self->demux)) {
786 return FALSE;
787 }
788
789 if (plm_demux_get_num_video_streams(self->demux) > 0) {
790 if (self->video_enabled) {
791 self->video_packet_type = PLM_DEMUX_PACKET_VIDEO_1;
792 }
793 self->video_buffer = plm_buffer_create_with_capacity(PLM_BUFFER_DEFAULT_SIZE);
794 plm_buffer_set_load_callback(self->video_buffer, plm_read_video_packet, self);
795 }
796
797 if (plm_demux_get_num_audio_streams(self->demux) > 0) {
798 if (self->audio_enabled) {
799 self->audio_packet_type = PLM_DEMUX_PACKET_AUDIO_1 + self->audio_stream_index;
800 }
801 self->audio_buffer = plm_buffer_create_with_capacity(PLM_BUFFER_DEFAULT_SIZE);
802 plm_buffer_set_load_callback(self->audio_buffer, plm_read_audio_packet, self);
803 }
804
805 if (self->video_buffer) {
806 self->video_decoder = plm_video_create_with_buffer(self->video_buffer, TRUE);
807 }
808
809 if (self->audio_buffer) {
810 self->audio_decoder = plm_audio_create_with_buffer(self->audio_buffer, TRUE);
811 }
812
813 self->has_decoders = TRUE;
814 return TRUE;
815}
816
817void plm_destroy(plm_t *self) {
818 if (self->video_decoder) {
819 plm_video_destroy(self->video_decoder);
820 }
821 if (self->audio_decoder) {
822 plm_audio_destroy(self->audio_decoder);
823 }
824
825 plm_demux_destroy(self->demux);
826 PLM_FREE(self);
827}
828
829int plm_get_audio_enabled(plm_t *self) { return self->audio_enabled; }
830
831int plm_has_headers(plm_t *self) {
832 if (!plm_demux_has_headers(self->demux)) {
833 return FALSE;
834 }
835
836 if (!plm_init_decoders(self)) {
837 return FALSE;
838 }
839
840 if ((self->video_decoder && !plm_video_has_header(self->video_decoder)) ||
841 (self->audio_decoder && !plm_audio_has_header(self->audio_decoder))) {
842 return FALSE;
843 }
844
845 return TRUE;
846}
847
848void plm_set_audio_enabled(plm_t *self, int enabled) {
849 self->audio_enabled = enabled;
850
851 if (!enabled) {
852 self->audio_packet_type = 0;
853 return;
854 }
855
856 self->audio_packet_type =
857 (plm_init_decoders(self) && self->audio_decoder) ? PLM_DEMUX_PACKET_AUDIO_1 + self->audio_stream_index : 0;
858}
859
860void plm_set_audio_stream(plm_t *self, int stream_index) {
861 if (stream_index < 0 || stream_index > 3) {
862 return;
863 }
864 self->audio_stream_index = stream_index;
865
866 // Set the correct audio_packet_type
867 plm_set_audio_enabled(self, self->audio_enabled);
868}
869
870int plm_get_video_enabled(plm_t *self) { return self->video_enabled; }
871
872void plm_set_video_enabled(plm_t *self, int enabled) {
873 self->video_enabled = enabled;
874
875 if (!enabled) {
876 self->video_packet_type = 0;
877 return;
878 }
879
880 self->video_packet_type = (plm_init_decoders(self) && self->video_decoder) ? PLM_DEMUX_PACKET_VIDEO_1 : 0;
881}
882
883int plm_get_num_video_streams(plm_t *self) { return plm_demux_get_num_video_streams(self->demux); }
884
885int plm_get_width(plm_t *self) {
886 return (plm_init_decoders(self) && self->video_decoder) ? plm_video_get_width(self->video_decoder) : 0;
887}
888
889int plm_get_height(plm_t *self) {
890 return (plm_init_decoders(self) && self->video_decoder) ? plm_video_get_height(self->video_decoder) : 0;
891}
892
893double plm_get_framerate(plm_t *self) {
894 return (plm_init_decoders(self) && self->video_decoder) ? plm_video_get_framerate(self->video_decoder) : 0;
895}
896
897int plm_get_num_audio_streams(plm_t *self) { return plm_demux_get_num_audio_streams(self->demux); }
898
899int plm_get_samplerate(plm_t *self) {
900 return (plm_init_decoders(self) && self->audio_decoder) ? plm_audio_get_samplerate(self->audio_decoder) : 0;
901}
902
903double plm_get_audio_lead_time(plm_t *self) { return self->audio_lead_time; }
904
905void plm_set_audio_lead_time(plm_t *self, double lead_time) { self->audio_lead_time = lead_time; }
906
907double plm_get_time(plm_t *self) { return self->time; }
908
909double plm_get_duration(plm_t *self) { return plm_demux_get_duration(self->demux, PLM_DEMUX_PACKET_VIDEO_1); }
910
911void plm_rewind(plm_t *self) {
912 if (self->video_decoder) {
913 plm_video_rewind(self->video_decoder);
914 }
915
916 if (self->audio_decoder) {
917 plm_audio_rewind(self->audio_decoder);
918 }
919
920 plm_demux_rewind(self->demux);
921 self->time = 0;
922}
923
924int plm_get_loop(plm_t *self) { return self->loop; }
925
926void plm_set_loop(plm_t *self, int loop) { self->loop = loop; }
927
928int plm_has_ended(plm_t *self) { return self->has_ended; }
929
930void plm_set_video_decode_callback(plm_t *self, plm_video_decode_callback fp, void *user) {
931 self->video_decode_callback = fp;
932 self->video_decode_callback_user_data = user;
933}
934
935void plm_set_audio_decode_callback(plm_t *self, plm_audio_decode_callback fp, void *user) {
936 self->audio_decode_callback = fp;
937 self->audio_decode_callback_user_data = user;
938}
939
940void plm_decode(plm_t *self, double tick) {
941 if (!plm_init_decoders(self)) {
942 return;
943 }
944
945 int decode_video = (self->video_decode_callback && self->video_packet_type);
946 int decode_audio = (self->audio_decode_callback && self->audio_packet_type);
947
948 if (!decode_video && !decode_audio) {
949 // Nothing to do here
950 return;
951 }
952
953 int did_decode = FALSE;
954 int decode_video_failed = FALSE;
955 int decode_audio_failed = FALSE;
956
957 double video_target_time = self->time + tick;
958 double audio_target_time = self->time + tick + self->audio_lead_time;
959
960 do {
961 did_decode = FALSE;
962
963 if (decode_video && plm_video_get_time(self->video_decoder) < video_target_time) {
964 plm_frame_t *frame = plm_video_decode(self->video_decoder);
965 if (frame) {
966 self->video_decode_callback(self, frame, self->video_decode_callback_user_data);
967 did_decode = TRUE;
968 } else {
969 decode_video_failed = TRUE;
970 }
971 }
972
973 if (decode_audio && plm_audio_get_time(self->audio_decoder) < audio_target_time) {
974 plm_samples_t *samples = plm_audio_decode(self->audio_decoder);
975 if (samples) {
976 self->audio_decode_callback(self, samples, self->audio_decode_callback_user_data);
977 did_decode = TRUE;
978 } else {
979 decode_audio_failed = TRUE;
980 }
981 }
982 } while (did_decode);
983
984 // Did all sources we wanted to decode fail and the demuxer is at the end?
985 if ((!decode_video || decode_video_failed) && (!decode_audio || decode_audio_failed) &&
986 plm_demux_has_ended(self->demux)) {
987 plm_handle_end(self);
988 return;
989 }
990
991 self->time += tick;
992}
993
994plm_frame_t *plm_decode_video(plm_t *self) {
995 if (!plm_init_decoders(self)) {
996 return NULL;
997 }
998
999 if (!self->video_packet_type) {
1000 return NULL;
1001 }
1002
1003 plm_frame_t *frame = plm_video_decode(self->video_decoder);
1004 if (frame) {
1005 self->time = frame->time;
1006 } else if (plm_demux_has_ended(self->demux)) {
1007 plm_handle_end(self);
1008 }
1009 return frame;
1010}
1011
1012plm_samples_t *plm_decode_audio(plm_t *self) {
1013 if (!plm_init_decoders(self)) {
1014 return NULL;
1015 }
1016
1017 if (!self->audio_packet_type) {
1018 return NULL;
1019 }
1020
1021 plm_samples_t *samples = plm_audio_decode(self->audio_decoder);
1022 if (samples) {
1023 self->time = samples->time;
1024 } else if (plm_demux_has_ended(self->demux)) {
1025 plm_handle_end(self);
1026 }
1027 return samples;
1028}
1029
1030void plm_handle_end(plm_t *self) {
1031 if (self->loop) {
1032 plm_rewind(self);
1033 } else {
1034 self->has_ended = TRUE;
1035 }
1036}
1037
1038void plm_read_video_packet(plm_buffer_t *buffer, void *user) {
1039 PLM_UNUSED(buffer);
1040 plm_t *self = (plm_t *)user;
1041 plm_read_packets(self, self->video_packet_type);
1042}
1043
1044void plm_read_audio_packet(plm_buffer_t *buffer, void *user) {
1045 PLM_UNUSED(buffer);
1046 plm_t *self = (plm_t *)user;
1047 plm_read_packets(self, self->audio_packet_type);
1048}
1049
1050void plm_read_packets(plm_t *self, int requested_type) {
1051 plm_packet_t *packet;
1052 while ((packet = plm_demux_decode(self->demux))) {
1053 if (packet->type == self->video_packet_type) {
1054 plm_buffer_write(self->video_buffer, packet->data, packet->length);
1055 } else if (packet->type == self->audio_packet_type) {
1056 plm_buffer_write(self->audio_buffer, packet->data, packet->length);
1057 }
1058
1059 if (packet->type == requested_type) {
1060 return;
1061 }
1062 }
1063
1064 if (plm_demux_has_ended(self->demux)) {
1065 if (self->video_buffer) {
1066 plm_buffer_signal_end(self->video_buffer);
1067 }
1068 if (self->audio_buffer) {
1069 plm_buffer_signal_end(self->audio_buffer);
1070 }
1071 }
1072}
1073
1074plm_frame_t *plm_seek_frame(plm_t *self, double time, int seek_exact) {
1075 if (!plm_init_decoders(self)) {
1076 return NULL;
1077 }
1078
1079 if (!self->video_packet_type) {
1080 return NULL;
1081 }
1082
1083 int type = self->video_packet_type;
1084
1085 double start_time = plm_demux_get_start_time(self->demux, type);
1086 double duration = plm_demux_get_duration(self->demux, type);
1087
1088 if (time < 0) {
1089 time = 0;
1090 } else if (time > duration) {
1091 time = duration;
1092 }
1093
1094 plm_packet_t *packet = plm_demux_seek(self->demux, time, type, TRUE);
1095 if (!packet) {
1096 return NULL;
1097 }
1098
1099 // Disable writing to the audio buffer while decoding video
1100 int previous_audio_packet_type = self->audio_packet_type;
1101 self->audio_packet_type = 0;
1102
1103 // Clear video buffer and decode the found packet
1104 plm_video_rewind(self->video_decoder);
1105 plm_video_set_time(self->video_decoder, packet->pts - start_time);
1106 plm_buffer_write(self->video_buffer, packet->data, packet->length);
1107 plm_frame_t *frame = plm_video_decode(self->video_decoder);
1108
1109 // If we want to seek to an exact frame, we have to decode all frames
1110 // on top of the intra frame we just jumped to.
1111 if (seek_exact) {
1112 while (frame && frame->time < time) {
1113 frame = plm_video_decode(self->video_decoder);
1114 }
1115 }
1116
1117 // Enable writing to the audio buffer again?
1118 self->audio_packet_type = previous_audio_packet_type;
1119
1120 if (frame) {
1121 self->time = frame->time;
1122 }
1123
1124 self->has_ended = FALSE;
1125 return frame;
1126}
1127
1128int plm_seek(plm_t *self, double time, int seek_exact) {
1129 plm_frame_t *frame = plm_seek_frame(self, time, seek_exact);
1130
1131 if (!frame) {
1132 return FALSE;
1133 }
1134
1135 if (self->video_decode_callback) {
1136 self->video_decode_callback(self, frame, self->video_decode_callback_user_data);
1137 }
1138
1139 // If audio is not enabled we are done here.
1140 if (!self->audio_packet_type) {
1141 return TRUE;
1142 }
1143
1144 // Sync up Audio. This demuxes more packets until the first audio packet
1145 // with a PTS greater than the current time is found. plm_decode() is then
1146 // called to decode enough audio data to satisfy the audio_lead_time.
1147
1148 double start_time = plm_demux_get_start_time(self->demux, self->video_packet_type);
1149 plm_audio_rewind(self->audio_decoder);
1150
1151 plm_packet_t *packet = NULL;
1152 while ((packet = plm_demux_decode(self->demux))) {
1153 if (packet->type == self->video_packet_type) {
1154 plm_buffer_write(self->video_buffer, packet->data, packet->length);
1155 } else if (packet->type == self->audio_packet_type && packet->pts - start_time > self->time) {
1156 plm_audio_set_time(self->audio_decoder, packet->pts - start_time);
1157 plm_buffer_write(self->audio_buffer, packet->data, packet->length);
1158 plm_decode(self, 0);
1159 break;
1160 }
1161 }
1162
1163 return TRUE;
1164}
1165
1166// -----------------------------------------------------------------------------
1167// plm_buffer implementation
1168
1169enum plm_buffer_mode { PLM_BUFFER_MODE_FILE, PLM_BUFFER_MODE_FIXED_MEM, PLM_BUFFER_MODE_RING, PLM_BUFFER_MODE_APPEND };
1170
1171struct plm_buffer_t {
1172 size_t bit_index;
1173 size_t capacity;
1174 size_t length;
1175 size_t total_size;
1176 int discard_read_bytes;
1177 int has_ended;
1178 int free_when_done;
1179 int close_when_done;
1180 FIL *fh;
1181 plm_buffer_load_callback load_callback;
1182 void *load_callback_user_data;
1183 uint8_t *bytes;
1184 enum plm_buffer_mode mode;
1185};
1186
1187typedef struct {
1188 int16_t index;
1189 int16_t value;
1190} plm_vlc_t;
1191
1192typedef struct {
1193 int16_t index;
1194 uint16_t value;
1195} plm_vlc_uint_t;
1196
1197void plm_buffer_seek(plm_buffer_t *self, size_t pos);
1198size_t plm_buffer_tell(plm_buffer_t *self);
1199void plm_buffer_discard_read_bytes(plm_buffer_t *self);
1200void plm_buffer_load_file_callback(plm_buffer_t *self, void *user);
1201
1202int plm_buffer_has(plm_buffer_t *self, size_t count);
1203int plm_buffer_read(plm_buffer_t *self, int count);
1204void plm_buffer_align(plm_buffer_t *self);
1205void plm_buffer_skip(plm_buffer_t *self, size_t count);
1206int plm_buffer_skip_bytes(plm_buffer_t *self, uint8_t v);
1207int plm_buffer_next_start_code(plm_buffer_t *self);
1208int plm_buffer_find_start_code(plm_buffer_t *self, int code);
1209int plm_buffer_no_start_code(plm_buffer_t *self);
1210int16_t plm_buffer_read_vlc(plm_buffer_t *self, const plm_vlc_t *table);
1211uint16_t plm_buffer_read_vlc_uint(plm_buffer_t *self, const plm_vlc_uint_t *table);
1212
1213plm_buffer_t *plm_buffer_create_with_filename(const char *filename) {
1214 FIL *fh = vexFileOpen(filename, "rb"); // fopen(filename, "rb");
1215 if (!fh) {
1216 return NULL;
1217 }
1218 return plm_buffer_create_with_file(fh, TRUE);
1219}
1220
1221plm_buffer_t *plm_buffer_create_with_file(FIL *fh, int close_when_done) {
1222 plm_buffer_t *self = plm_buffer_create_with_capacity(PLM_BUFFER_DEFAULT_SIZE);
1223 self->fh = fh;
1224 self->close_when_done = close_when_done;
1225 self->mode = PLM_BUFFER_MODE_FILE;
1226 self->discard_read_bytes = TRUE;
1227
1228 vexFileSeek(self->fh, 0, SEEK_END);
1229 self->total_size = vexFileTell(self->fh);
1230 vexFileSeek(self->fh, 0, SEEK_SET);
1231
1232 plm_buffer_set_load_callback(self, plm_buffer_load_file_callback, NULL);
1233 return self;
1234}
1235
1236plm_buffer_t *plm_buffer_create_with_memory(uint8_t *bytes, size_t length, int free_when_done) {
1237 plm_buffer_t *self = (plm_buffer_t *)PLM_MALLOC(sizeof(plm_buffer_t));
1238 memset(self, 0, sizeof(plm_buffer_t));
1239 self->capacity = length;
1240 self->length = length;
1241 self->total_size = length;
1242 self->free_when_done = free_when_done;
1243 self->bytes = bytes;
1244 self->mode = PLM_BUFFER_MODE_FIXED_MEM;
1245 self->discard_read_bytes = FALSE;
1246 return self;
1247}
1248
1249plm_buffer_t *plm_buffer_create_with_capacity(size_t capacity) {
1250 plm_buffer_t *self = (plm_buffer_t *)PLM_MALLOC(sizeof(plm_buffer_t));
1251 memset(self, 0, sizeof(plm_buffer_t));
1252 self->capacity = capacity;
1253 self->free_when_done = TRUE;
1254 self->bytes = (uint8_t *)PLM_MALLOC(capacity);
1255 self->mode = PLM_BUFFER_MODE_RING;
1256 self->discard_read_bytes = TRUE;
1257 return self;
1258}
1259
1260plm_buffer_t *plm_buffer_create_for_appending(size_t initial_capacity) {
1261 plm_buffer_t *self = plm_buffer_create_with_capacity(initial_capacity);
1262 self->mode = PLM_BUFFER_MODE_APPEND;
1263 self->discard_read_bytes = FALSE;
1264 return self;
1265}
1266
1267void plm_buffer_destroy(plm_buffer_t *self) {
1268 if (self->fh && self->close_when_done) {
1269 vexFileClose(self->fh);
1270 }
1271 if (self->free_when_done) {
1272 PLM_FREE(self->bytes);
1273 }
1274 PLM_FREE(self);
1275}
1276
1277size_t plm_buffer_get_size(plm_buffer_t *self) {
1278 return (self->mode == PLM_BUFFER_MODE_FILE) ? self->total_size : self->length;
1279}
1280
1281size_t plm_buffer_get_remaining(plm_buffer_t *self) { return self->length - (self->bit_index >> 3); }
1282
1283size_t plm_buffer_write(plm_buffer_t *self, uint8_t *bytes, size_t length) {
1284 if (self->mode == PLM_BUFFER_MODE_FIXED_MEM) {
1285 return 0;
1286 }
1287
1288 if (self->discard_read_bytes) {
1289 // This should be a ring buffer, but instead it just shifts all unread
1290 // data to the beginning of the buffer and appends new data at the end.
1291 // Seems to be good enough.
1292
1293 plm_buffer_discard_read_bytes(self);
1294 if (self->mode == PLM_BUFFER_MODE_RING) {
1295 self->total_size = 0;
1296 }
1297 }
1298
1299 // Do we have to resize to fit the new data?
1300 size_t bytes_available = self->capacity - self->length;
1301 if (bytes_available < length) {
1302 size_t new_size = self->capacity;
1303 do {
1304 new_size *= 2;
1305 } while (new_size - self->length < length);
1306 self->bytes = (uint8_t *)PLM_REALLOC(self->bytes, new_size);
1307 self->capacity = new_size;
1308 }
1309
1310 memcpy(self->bytes + self->length, bytes, length);
1311 self->length += length;
1312 self->has_ended = FALSE;
1313 return length;
1314}
1315
1316void plm_buffer_signal_end(plm_buffer_t *self) { self->total_size = self->length; }
1317
1318void plm_buffer_set_load_callback(plm_buffer_t *self, plm_buffer_load_callback fp, void *user) {
1319 self->load_callback = fp;
1320 self->load_callback_user_data = user;
1321}
1322
1323void plm_buffer_rewind(plm_buffer_t *self) { plm_buffer_seek(self, 0); }
1324
1325void plm_buffer_seek(plm_buffer_t *self, size_t pos) {
1326 self->has_ended = FALSE;
1327
1328 if (self->mode == PLM_BUFFER_MODE_FILE) {
1329 vexFileSeek(self->fh, pos, SEEK_SET);
1330 self->bit_index = 0;
1331 self->length = 0;
1332 } else if (self->mode == PLM_BUFFER_MODE_RING) {
1333 if (pos != 0) {
1334 // Seeking to non-0 is forbidden for dynamic-mem buffers
1335 return;
1336 }
1337 self->bit_index = 0;
1338 self->length = 0;
1339 self->total_size = 0;
1340 } else if (pos < self->length) {
1341 self->bit_index = pos << 3;
1342 }
1343}
1344
1345size_t plm_buffer_tell(plm_buffer_t *self) {
1346 return self->mode == PLM_BUFFER_MODE_FILE ? vexFileTell(self->fh) + (self->bit_index >> 3) - self->length
1347 : self->bit_index >> 3;
1348}
1349
1350void plm_buffer_discard_read_bytes(plm_buffer_t *self) {
1351 size_t byte_pos = self->bit_index >> 3;
1352 if (byte_pos == self->length) {
1353 self->bit_index = 0;
1354 self->length = 0;
1355 } else if (byte_pos > 0) {
1356 memmove(self->bytes, self->bytes + byte_pos, self->length - byte_pos);
1357 self->bit_index -= byte_pos << 3;
1358 self->length -= byte_pos;
1359 }
1360}
1361
1362void plm_buffer_load_file_callback(plm_buffer_t *self, void *user) {
1363 PLM_UNUSED(user);
1364
1365 if (self->discard_read_bytes) {
1366 plm_buffer_discard_read_bytes(self);
1367 }
1368
1369 size_t bytes_available = self->capacity - self->length;
1370 size_t bytes_read = vexFileRead((char *)self->bytes + self->length, 1, bytes_available, self->fh);
1371 self->length += bytes_read;
1372
1373 if (bytes_read == 0) {
1374 self->has_ended = TRUE;
1375 }
1376}
1377
1378int plm_buffer_has_ended(plm_buffer_t *self) { return self->has_ended; }
1379
1380int plm_buffer_has(plm_buffer_t *self, size_t count) {
1381 if (((self->length << 3) - self->bit_index) >= count) {
1382 return TRUE;
1383 }
1384
1385 if (self->load_callback) {
1386 self->load_callback(self, self->load_callback_user_data);
1387
1388 if (((self->length << 3) - self->bit_index) >= count) {
1389 return TRUE;
1390 }
1391 }
1392
1393 if (self->total_size != 0 && self->length == self->total_size) {
1394 self->has_ended = TRUE;
1395 }
1396 return FALSE;
1397}
1398
1399int plm_buffer_read(plm_buffer_t *self, int count) {
1400 if (!plm_buffer_has(self, count)) {
1401 return 0;
1402 }
1403
1404 int value = 0;
1405 while (count) {
1406 int current_byte = self->bytes[self->bit_index >> 3];
1407
1408 int remaining = 8 - (self->bit_index & 7); // Remaining bits in byte
1409 int read = remaining < count ? remaining : count; // Bits in self run
1410 int shift = remaining - read;
1411 int mask = (0xff >> (8 - read));
1412
1413 value = (value << read) | ((current_byte & (mask << shift)) >> shift);
1414
1415 self->bit_index += read;
1416 count -= read;
1417 }
1418
1419 return value;
1420}
1421
1422void plm_buffer_align(plm_buffer_t *self) {
1423 self->bit_index = ((self->bit_index + 7) >> 3) << 3; // Align to next byte
1424}
1425
1426void plm_buffer_skip(plm_buffer_t *self, size_t count) {
1427 if (plm_buffer_has(self, count)) {
1428 self->bit_index += count;
1429 }
1430}
1431
1432int plm_buffer_skip_bytes(plm_buffer_t *self, uint8_t v) {
1433 plm_buffer_align(self);
1434 int skipped = 0;
1435 while (plm_buffer_has(self, 8) && self->bytes[self->bit_index >> 3] == v) {
1436 self->bit_index += 8;
1437 skipped++;
1438 }
1439 return skipped;
1440}
1441
1442int plm_buffer_next_start_code(plm_buffer_t *self) {
1443 plm_buffer_align(self);
1444
1445 while (plm_buffer_has(self, (5 << 3))) {
1446 size_t byte_index = (self->bit_index) >> 3;
1447 if (self->bytes[byte_index] == 0x00 && self->bytes[byte_index + 1] == 0x00 && self->bytes[byte_index + 2] == 0x01) {
1448 self->bit_index = (byte_index + 4) << 3;
1449 return self->bytes[byte_index + 3];
1450 }
1451 self->bit_index += 8;
1452 }
1453 return -1;
1454}
1455
1456int plm_buffer_find_start_code(plm_buffer_t *self, int code) {
1457 int current = 0;
1458 while (TRUE) {
1459 current = plm_buffer_next_start_code(self);
1460 if (current == code || current == -1) {
1461 return current;
1462 }
1463 }
1464 return -1;
1465}
1466
1467int plm_buffer_has_start_code(plm_buffer_t *self, int code) {
1468 size_t previous_bit_index = self->bit_index;
1469 int previous_discard_read_bytes = self->discard_read_bytes;
1470
1471 self->discard_read_bytes = FALSE;
1472 int current = plm_buffer_find_start_code(self, code);
1473
1474 self->bit_index = previous_bit_index;
1475 self->discard_read_bytes = previous_discard_read_bytes;
1476 return current;
1477}
1478
1479int plm_buffer_peek_non_zero(plm_buffer_t *self, int bit_count) {
1480 if (!plm_buffer_has(self, bit_count)) {
1481 return FALSE;
1482 }
1483
1484 int val = plm_buffer_read(self, bit_count);
1485 self->bit_index -= bit_count;
1486 return val != 0;
1487}
1488
1489int16_t plm_buffer_read_vlc(plm_buffer_t *self, const plm_vlc_t *table) {
1490 plm_vlc_t state = {0, 0};
1491 do {
1492 state = table[state.index + plm_buffer_read(self, 1)];
1493 } while (state.index > 0);
1494 return state.value;
1495}
1496
1497uint16_t plm_buffer_read_vlc_uint(plm_buffer_t *self, const plm_vlc_uint_t *table) {
1498 return (uint16_t)plm_buffer_read_vlc(self, (const plm_vlc_t *)table);
1499}
1500
1501// ----------------------------------------------------------------------------
1502// plm_demux implementation
1503
1504static const int PLM_START_PACK = 0xBA;
1505static const int PLM_START_END = 0xB9;
1506static const int PLM_START_SYSTEM = 0xBB;
1507
1508struct plm_demux_t {
1509 plm_buffer_t *buffer;
1510 int destroy_buffer_when_done;
1511 double system_clock_ref;
1512
1513 size_t last_file_size;
1514 double last_decoded_pts;
1515 double start_time;
1516 double duration;
1517
1518 int start_code;
1519 int has_pack_header;
1520 int has_system_header;
1521 int has_headers;
1522
1523 int num_audio_streams;
1524 int num_video_streams;
1525 plm_packet_t current_packet;
1526 plm_packet_t next_packet;
1527};
1528
1529void plm_demux_buffer_seek(plm_demux_t *self, size_t pos);
1530double plm_demux_decode_time(plm_demux_t *self);
1531plm_packet_t *plm_demux_decode_packet(plm_demux_t *self, int type);
1532plm_packet_t *plm_demux_get_packet(plm_demux_t *self);
1533
1534plm_demux_t *plm_demux_create(plm_buffer_t *buffer, int destroy_when_done) {
1535 plm_demux_t *self = (plm_demux_t *)PLM_MALLOC(sizeof(plm_demux_t));
1536 memset(self, 0, sizeof(plm_demux_t));
1537
1538 self->buffer = buffer;
1539 self->destroy_buffer_when_done = destroy_when_done;
1540
1541 self->start_time = PLM_PACKET_INVALID_TS;
1542 self->duration = PLM_PACKET_INVALID_TS;
1543 self->start_code = -1;
1544
1545 plm_demux_has_headers(self);
1546 return self;
1547}
1548
1549void plm_demux_destroy(plm_demux_t *self) {
1550 if (self->destroy_buffer_when_done) {
1551 plm_buffer_destroy(self->buffer);
1552 }
1553 PLM_FREE(self);
1554}
1555
1556int plm_demux_has_headers(plm_demux_t *self) {
1557 if (self->has_headers) {
1558 return TRUE;
1559 }
1560
1561 // Decode pack header
1562 if (!self->has_pack_header) {
1563 if (self->start_code != PLM_START_PACK && plm_buffer_find_start_code(self->buffer, PLM_START_PACK) == -1) {
1564 return FALSE;
1565 }
1566
1567 self->start_code = PLM_START_PACK;
1568 if (!plm_buffer_has(self->buffer, 64)) {
1569 return FALSE;
1570 }
1571 self->start_code = -1;
1572
1573 if (plm_buffer_read(self->buffer, 4) != 0x02) {
1574 return FALSE;
1575 }
1576
1577 self->system_clock_ref = plm_demux_decode_time(self);
1578 plm_buffer_skip(self->buffer, 1);
1579 plm_buffer_skip(self->buffer, 22); // mux_rate * 50
1580 plm_buffer_skip(self->buffer, 1);
1581
1582 self->has_pack_header = TRUE;
1583 }
1584
1585 // Decode system header
1586 if (!self->has_system_header) {
1587 if (self->start_code != PLM_START_SYSTEM && plm_buffer_find_start_code(self->buffer, PLM_START_SYSTEM) == -1) {
1588 return FALSE;
1589 }
1590
1591 self->start_code = PLM_START_SYSTEM;
1592 if (!plm_buffer_has(self->buffer, 56)) {
1593 return FALSE;
1594 }
1595 self->start_code = -1;
1596
1597 plm_buffer_skip(self->buffer, 16); // header_length
1598 plm_buffer_skip(self->buffer, 24); // rate bound
1599 self->num_audio_streams = plm_buffer_read(self->buffer, 6);
1600 plm_buffer_skip(self->buffer, 5); // misc flags
1601 self->num_video_streams = plm_buffer_read(self->buffer, 5);
1602
1603 self->has_system_header = TRUE;
1604 }
1605
1606 self->has_headers = TRUE;
1607 return TRUE;
1608}
1609
1610int plm_demux_get_num_video_streams(plm_demux_t *self) {
1611 return plm_demux_has_headers(self) ? self->num_video_streams : 0;
1612}
1613
1614int plm_demux_get_num_audio_streams(plm_demux_t *self) {
1615 return plm_demux_has_headers(self) ? self->num_audio_streams : 0;
1616}
1617
1618void plm_demux_rewind(plm_demux_t *self) {
1619 plm_buffer_rewind(self->buffer);
1620 self->current_packet.length = 0;
1621 self->next_packet.length = 0;
1622 self->start_code = -1;
1623}
1624
1625int plm_demux_has_ended(plm_demux_t *self) { return plm_buffer_has_ended(self->buffer); }
1626
1627void plm_demux_buffer_seek(plm_demux_t *self, size_t pos) {
1628 plm_buffer_seek(self->buffer, pos);
1629 self->current_packet.length = 0;
1630 self->next_packet.length = 0;
1631 self->start_code = -1;
1632}
1633
1634double plm_demux_get_start_time(plm_demux_t *self, int type) {
1635 if (self->start_time != PLM_PACKET_INVALID_TS) {
1636 return self->start_time;
1637 }
1638
1639 int previous_pos = plm_buffer_tell(self->buffer);
1640 int previous_start_code = self->start_code;
1641
1642 // Find first video PTS
1643 plm_demux_rewind(self);
1644 do {
1645 plm_packet_t *packet = plm_demux_decode(self);
1646 if (!packet) {
1647 break;
1648 }
1649 if (packet->type == type) {
1650 self->start_time = packet->pts;
1651 }
1652 } while (self->start_time == PLM_PACKET_INVALID_TS);
1653
1654 plm_demux_buffer_seek(self, previous_pos);
1655 self->start_code = previous_start_code;
1656 return self->start_time;
1657}
1658
1659double plm_demux_get_duration(plm_demux_t *self, int type) {
1660 size_t file_size = plm_buffer_get_size(self->buffer);
1661
1662 if (self->duration != PLM_PACKET_INVALID_TS && self->last_file_size == file_size) {
1663 return self->duration;
1664 }
1665
1666 size_t previous_pos = plm_buffer_tell(self->buffer);
1667 int previous_start_code = self->start_code;
1668
1669 // Find last video PTS. Start searching 64kb from the end and go further
1670 // back if needed.
1671 long start_range = 64 * 1024;
1672 long max_range = 4096 * 1024;
1673 for (long range = start_range; range <= max_range; range *= 2) {
1674 long seek_pos = file_size - range;
1675 if (seek_pos < 0) {
1676 seek_pos = 0;
1677 range = max_range; // Make sure to bail after this round
1678 }
1679 plm_demux_buffer_seek(self, seek_pos);
1680 self->current_packet.length = 0;
1681
1682 double last_pts = PLM_PACKET_INVALID_TS;
1683 plm_packet_t *packet = NULL;
1684 while ((packet = plm_demux_decode(self))) {
1685 if (packet->pts != PLM_PACKET_INVALID_TS && packet->type == type) {
1686 last_pts = packet->pts;
1687 }
1688 }
1689 if (last_pts != PLM_PACKET_INVALID_TS) {
1690 self->duration = last_pts - plm_demux_get_start_time(self, type);
1691 break;
1692 }
1693 }
1694
1695 plm_demux_buffer_seek(self, previous_pos);
1696 self->start_code = previous_start_code;
1697 self->last_file_size = file_size;
1698 return self->duration;
1699}
1700
1701plm_packet_t *plm_demux_seek(plm_demux_t *self, double seek_time, int type, int force_intra) {
1702 if (!plm_demux_has_headers(self)) {
1703 return NULL;
1704 }
1705
1706 // Using the current time, current byte position and the average bytes per
1707 // second for this file, try to jump to a byte position that hopefully has
1708 // packets containing timestamps within one second before to the desired
1709 // seek_time.
1710
1711 // If we hit close to the seek_time scan through all packets to find the
1712 // last one (just before the seek_time) containing an intra frame.
1713 // Otherwise we should at least be closer than before. Calculate the bytes
1714 // per second for the jumped range and jump again.
1715
1716 // The number of retries here is hard-limited to a generous amount. Usually
1717 // the correct range is found after 1--5 jumps, even for files with very
1718 // variable bitrates. If significantly more jumps are needed, there's
1719 // probably something wrong with the file and we just avoid getting into an
1720 // infinite loop. 32 retries should be enough for anybody.
1721
1722 double duration = plm_demux_get_duration(self, type);
1723 long file_size = plm_buffer_get_size(self->buffer);
1724 long byterate = file_size / duration;
1725
1726 double cur_time = self->last_decoded_pts;
1727 double scan_span = 1;
1728
1729 if (seek_time > duration) {
1730 seek_time = duration;
1731 } else if (seek_time < 0) {
1732 seek_time = 0;
1733 }
1734 seek_time += self->start_time;
1735
1736 for (int retry = 0; retry < 32; retry++) {
1737 int found_packet_with_pts = FALSE;
1738 int found_packet_in_range = FALSE;
1739 long last_valid_packet_start = -1;
1740 double first_packet_time = PLM_PACKET_INVALID_TS;
1741
1742 long cur_pos = plm_buffer_tell(self->buffer);
1743
1744 // Estimate byte offset and jump to it.
1745 long offset = (seek_time - cur_time - scan_span) * byterate;
1746 long seek_pos = cur_pos + offset;
1747 if (seek_pos < 0) {
1748 seek_pos = 0;
1749 } else if (seek_pos > file_size - 256) {
1750 seek_pos = file_size - 256;
1751 }
1752
1753 plm_demux_buffer_seek(self, seek_pos);
1754
1755 // Scan through all packets up to the seek_time to find the last packet
1756 // containing an intra frame.
1757 while (plm_buffer_find_start_code(self->buffer, type) != -1) {
1758 long packet_start = plm_buffer_tell(self->buffer);
1759 plm_packet_t *packet = plm_demux_decode_packet(self, type);
1760
1761 // Skip packet if it has no PTS
1762 if (!packet || packet->pts == PLM_PACKET_INVALID_TS) {
1763 continue;
1764 }
1765
1766 // Bail scanning through packets if we hit one that is outside
1767 // seek_time - scan_span.
1768 // We also adjust the cur_time and byterate values here so the next
1769 // iteration can be a bit more precise.
1770 if (packet->pts > seek_time || packet->pts < seek_time - scan_span) {
1771 found_packet_with_pts = TRUE;
1772 byterate = (seek_pos - cur_pos) / (packet->pts - cur_time);
1773 cur_time = packet->pts;
1774 break;
1775 }
1776
1777 // If we are still here, it means this packet is in close range to
1778 // the seek_time. If this is the first packet for this jump position
1779 // record the PTS. If we later have to back off, when there was no
1780 // intra frame in this range, we can lower the seek_time to not scan
1781 // this range again.
1782 if (!found_packet_in_range) {
1783 found_packet_in_range = TRUE;
1784 first_packet_time = packet->pts;
1785 }
1786
1787 // Check if this is an intra frame packet. If so, record the buffer
1788 // position of the start of this packet. We want to jump back to it
1789 // later, when we know it's the last intra frame before desired
1790 // seek time.
1791 if (force_intra) {
1792 for (size_t i = 0; i < packet->length - 6; i++) {
1793 // Find the START_PICTURE code
1794 if (packet->data[i] == 0x00 && packet->data[i + 1] == 0x00 && packet->data[i + 2] == 0x01 &&
1795 packet->data[i + 3] == 0x00) {
1796 // Bits 11--13 in the picture header contain the frame
1797 // type, where 1=Intra
1798 if ((packet->data[i + 5] & 0x38) == 8) {
1799 last_valid_packet_start = packet_start;
1800 }
1801 break;
1802 }
1803 }
1804 }
1805
1806 // If we don't want intra frames, just use the last PTS found.
1807 else {
1808 last_valid_packet_start = packet_start;
1809 }
1810 }
1811
1812 // If there was at least one intra frame in the range scanned above,
1813 // our search is over. Jump back to the packet and decode it again.
1814 if (last_valid_packet_start != -1) {
1815 plm_demux_buffer_seek(self, last_valid_packet_start);
1816 return plm_demux_decode_packet(self, type);
1817 }
1818
1819 // If we hit the right range, but still found no intra frame, we have
1820 // to increases the scan_span. This is done exponentially to also handle
1821 // video files with very few intra frames.
1822 else if (found_packet_in_range) {
1823 scan_span *= 2;
1824 seek_time = first_packet_time;
1825 }
1826
1827 // If we didn't find any packet with a PTS, it probably means we reached
1828 // the end of the file. Estimate byterate and cur_time accordingly.
1829 else if (!found_packet_with_pts) {
1830 byterate = (seek_pos - cur_pos) / (duration - cur_time);
1831 cur_time = duration;
1832 }
1833 }
1834
1835 return NULL;
1836}
1837
1838plm_packet_t *plm_demux_decode(plm_demux_t *self) {
1839 if (!plm_demux_has_headers(self)) {
1840 return NULL;
1841 }
1842
1843 if (self->current_packet.length) {
1844 size_t bits_till_next_packet = self->current_packet.length << 3;
1845 if (!plm_buffer_has(self->buffer, bits_till_next_packet)) {
1846 return NULL;
1847 }
1848 plm_buffer_skip(self->buffer, bits_till_next_packet);
1849 self->current_packet.length = 0;
1850 }
1851
1852 // Pending packet waiting for data?
1853 if (self->next_packet.length) {
1854 return plm_demux_get_packet(self);
1855 }
1856
1857 // Pending packet waiting for header?
1858 if (self->start_code != -1) {
1859 return plm_demux_decode_packet(self, self->start_code);
1860 }
1861
1862 do {
1863 self->start_code = plm_buffer_next_start_code(self->buffer);
1864 if (self->start_code == PLM_DEMUX_PACKET_VIDEO_1 || self->start_code == PLM_DEMUX_PACKET_PRIVATE ||
1865 (self->start_code >= PLM_DEMUX_PACKET_AUDIO_1 && self->start_code <= PLM_DEMUX_PACKET_AUDIO_4)) {
1866 return plm_demux_decode_packet(self, self->start_code);
1867 }
1868 } while (self->start_code != -1);
1869
1870 return NULL;
1871}
1872
1873double plm_demux_decode_time(plm_demux_t *self) {
1874 int64_t clock = plm_buffer_read(self->buffer, 3) << 30;
1875 plm_buffer_skip(self->buffer, 1);
1876 clock |= plm_buffer_read(self->buffer, 15) << 15;
1877 plm_buffer_skip(self->buffer, 1);
1878 clock |= plm_buffer_read(self->buffer, 15);
1879 plm_buffer_skip(self->buffer, 1);
1880 return (double)clock / 90000.0;
1881}
1882
1883plm_packet_t *plm_demux_decode_packet(plm_demux_t *self, int type) {
1884 if (!plm_buffer_has(self->buffer, 16 << 3)) {
1885 return NULL;
1886 }
1887
1888 self->start_code = -1;
1889
1890 self->next_packet.type = type;
1891 self->next_packet.length = plm_buffer_read(self->buffer, 16);
1892 self->next_packet.length -= plm_buffer_skip_bytes(self->buffer, 0xff); // stuffing
1893
1894 // skip P-STD
1895 if (plm_buffer_read(self->buffer, 2) == 0x01) {
1896 plm_buffer_skip(self->buffer, 16);
1897 self->next_packet.length -= 2;
1898 }
1899
1900 int pts_dts_marker = plm_buffer_read(self->buffer, 2);
1901 if (pts_dts_marker == 0x03) {
1902 self->next_packet.pts = plm_demux_decode_time(self);
1903 self->last_decoded_pts = self->next_packet.pts;
1904 plm_buffer_skip(self->buffer, 40); // skip dts
1905 self->next_packet.length -= 10;
1906 } else if (pts_dts_marker == 0x02) {
1907 self->next_packet.pts = plm_demux_decode_time(self);
1908 self->last_decoded_pts = self->next_packet.pts;
1909 self->next_packet.length -= 5;
1910 } else if (pts_dts_marker == 0x00) {
1911 self->next_packet.pts = PLM_PACKET_INVALID_TS;
1912 plm_buffer_skip(self->buffer, 4);
1913 self->next_packet.length -= 1;
1914 } else {
1915 return NULL; // invalid
1916 }
1917
1918 return plm_demux_get_packet(self);
1919}
1920
1921plm_packet_t *plm_demux_get_packet(plm_demux_t *self) {
1922 if (!plm_buffer_has(self->buffer, self->next_packet.length << 3)) {
1923 return NULL;
1924 }
1925
1926 self->current_packet.data = self->buffer->bytes + (self->buffer->bit_index >> 3);
1927 self->current_packet.length = self->next_packet.length;
1928 self->current_packet.type = self->next_packet.type;
1929 self->current_packet.pts = self->next_packet.pts;
1930
1931 self->next_packet.length = 0;
1932 return &self->current_packet;
1933}
1934
1935// -----------------------------------------------------------------------------
1936// plm_video implementation
1937
1938// Inspired by Java MPEG-1 Video Decoder and Player by Zoltan Korandi
1939// https://sourceforge.net/projects/javampeg1video/
1940
1941static const int PLM_VIDEO_PICTURE_TYPE_INTRA = 1;
1942static const int PLM_VIDEO_PICTURE_TYPE_PREDICTIVE = 2;
1943static const int PLM_VIDEO_PICTURE_TYPE_B = 3;
1944
1945static const int PLM_START_SEQUENCE = 0xB3;
1946static const int PLM_START_SLICE_FIRST = 0x01;
1947static const int PLM_START_SLICE_LAST = 0xAF;
1948static const int PLM_START_PICTURE = 0x00;
1949static const int PLM_START_EXTENSION = 0xB5;
1950static const int PLM_START_USER_DATA = 0xB2;
1951
1952#define PLM_START_IS_SLICE(c) (c >= PLM_START_SLICE_FIRST && c <= PLM_START_SLICE_LAST)
1953
1954static const double PLM_VIDEO_PICTURE_RATE[] = {0.000, 23.976, 24.000, 25.000, 29.970, 30.000, 50.000, 59.940,
1955 60.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000};
1956
1957static const uint8_t PLM_VIDEO_ZIG_ZAG[] = {0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
1958 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
1959 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
1960 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63};
1961
1962static const uint8_t PLM_VIDEO_INTRA_QUANT_MATRIX[] = {8, 16, 19, 22, 26, 27, 29, 34, 16, 16, 22, 24, 27, 29, 34, 37,
1963 19, 22, 26, 27, 29, 34, 34, 38, 22, 22, 26, 27, 29, 34, 37, 40,
1964 22, 26, 27, 29, 32, 35, 40, 48, 26, 27, 29, 32, 35, 40, 48, 58,
1965 26, 27, 29, 34, 38, 46, 56, 69, 27, 29, 35, 38, 46, 56, 69, 83};
1966
1967static const uint8_t PLM_VIDEO_NON_INTRA_QUANT_MATRIX[] = {
1968 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
1969 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
1970 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
1971
1972static const uint8_t PLM_VIDEO_PREMULTIPLIER_MATRIX[] = {32, 44, 42, 38, 32, 25, 17, 9, 44, 62, 58, 52, 44, 35, 24, 12,
1973 42, 58, 55, 49, 42, 33, 23, 12, 38, 52, 49, 44, 38, 30, 20, 10,
1974 32, 44, 42, 38, 32, 25, 17, 9, 25, 35, 33, 30, 25, 20, 14, 7,
1975 17, 24, 23, 20, 17, 14, 9, 5, 9, 12, 12, 10, 9, 7, 5, 2};
1976
1977static const plm_vlc_t PLM_VIDEO_MACROBLOCK_ADDRESS_INCREMENT[] = {
1978 {1 << 1, 0}, {0, 1}, // 0: x
1979 {2 << 1, 0}, {3 << 1, 0}, // 1: 0x
1980 {4 << 1, 0}, {5 << 1, 0}, // 2: 00x
1981 {0, 3}, {0, 2}, // 3: 01x
1982 {6 << 1, 0}, {7 << 1, 0}, // 4: 000x
1983 {0, 5}, {0, 4}, // 5: 001x
1984 {8 << 1, 0}, {9 << 1, 0}, // 6: 0000x
1985 {0, 7}, {0, 6}, // 7: 0001x
1986 {10 << 1, 0}, {11 << 1, 0}, // 8: 0000 0x
1987 {12 << 1, 0}, {13 << 1, 0}, // 9: 0000 1x
1988 {14 << 1, 0}, {15 << 1, 0}, // 10: 0000 00x
1989 {16 << 1, 0}, {17 << 1, 0}, // 11: 0000 01x
1990 {18 << 1, 0}, {19 << 1, 0}, // 12: 0000 10x
1991 {0, 9}, {0, 8}, // 13: 0000 11x
1992 {-1, 0}, {20 << 1, 0}, // 14: 0000 000x
1993 {-1, 0}, {21 << 1, 0}, // 15: 0000 001x
1994 {22 << 1, 0}, {23 << 1, 0}, // 16: 0000 010x
1995 {0, 15}, {0, 14}, // 17: 0000 011x
1996 {0, 13}, {0, 12}, // 18: 0000 100x
1997 {0, 11}, {0, 10}, // 19: 0000 101x
1998 {24 << 1, 0}, {25 << 1, 0}, // 20: 0000 0001x
1999 {26 << 1, 0}, {27 << 1, 0}, // 21: 0000 0011x
2000 {28 << 1, 0}, {29 << 1, 0}, // 22: 0000 0100x
2001 {30 << 1, 0}, {31 << 1, 0}, // 23: 0000 0101x
2002 {32 << 1, 0}, {-1, 0}, // 24: 0000 0001 0x
2003 {-1, 0}, {33 << 1, 0}, // 25: 0000 0001 1x
2004 {34 << 1, 0}, {35 << 1, 0}, // 26: 0000 0011 0x
2005 {36 << 1, 0}, {37 << 1, 0}, // 27: 0000 0011 1x
2006 {38 << 1, 0}, {39 << 1, 0}, // 28: 0000 0100 0x
2007 {0, 21}, {0, 20}, // 29: 0000 0100 1x
2008 {0, 19}, {0, 18}, // 30: 0000 0101 0x
2009 {0, 17}, {0, 16}, // 31: 0000 0101 1x
2010 {0, 35}, {-1, 0}, // 32: 0000 0001 00x
2011 {-1, 0}, {0, 34}, // 33: 0000 0001 11x
2012 {0, 33}, {0, 32}, // 34: 0000 0011 00x
2013 {0, 31}, {0, 30}, // 35: 0000 0011 01x
2014 {0, 29}, {0, 28}, // 36: 0000 0011 10x
2015 {0, 27}, {0, 26}, // 37: 0000 0011 11x
2016 {0, 25}, {0, 24}, // 38: 0000 0100 00x
2017 {0, 23}, {0, 22}, // 39: 0000 0100 01x
2018};
2019
2020static const plm_vlc_t PLM_VIDEO_MACROBLOCK_TYPE_INTRA[] = {
2021 {1 << 1, 0},
2022 {0, 0x01}, // 0: x
2023 {-1, 0},
2024 {0, 0x11}, // 1: 0x
2025};
2026
2027static const plm_vlc_t PLM_VIDEO_MACROBLOCK_TYPE_PREDICTIVE[] = {
2028 {1 << 1, 0}, {0, 0x0a}, // 0: x
2029 {2 << 1, 0}, {0, 0x02}, // 1: 0x
2030 {3 << 1, 0}, {0, 0x08}, // 2: 00x
2031 {4 << 1, 0}, {5 << 1, 0}, // 3: 000x
2032 {6 << 1, 0}, {0, 0x12}, // 4: 0000x
2033 {0, 0x1a}, {0, 0x01}, // 5: 0001x
2034 {-1, 0}, {0, 0x11}, // 6: 0000 0x
2035};
2036
2037static const plm_vlc_t PLM_VIDEO_MACROBLOCK_TYPE_B[] = {
2038 {1 << 1, 0}, {2 << 1, 0}, // 0: x
2039 {3 << 1, 0}, {4 << 1, 0}, // 1: 0x
2040 {0, 0x0c}, {0, 0x0e}, // 2: 1x
2041 {5 << 1, 0}, {6 << 1, 0}, // 3: 00x
2042 {0, 0x04}, {0, 0x06}, // 4: 01x
2043 {7 << 1, 0}, {8 << 1, 0}, // 5: 000x
2044 {0, 0x08}, {0, 0x0a}, // 6: 001x
2045 {9 << 1, 0}, {10 << 1, 0}, // 7: 0000x
2046 {0, 0x1e}, {0, 0x01}, // 8: 0001x
2047 {-1, 0}, {0, 0x11}, // 9: 0000 0x
2048 {0, 0x16}, {0, 0x1a}, // 10: 0000 1x
2049};
2050
2051static const plm_vlc_t *PLM_VIDEO_MACROBLOCK_TYPE[] = {
2052 NULL, PLM_VIDEO_MACROBLOCK_TYPE_INTRA, PLM_VIDEO_MACROBLOCK_TYPE_PREDICTIVE, PLM_VIDEO_MACROBLOCK_TYPE_B};
2053
2054static const plm_vlc_t PLM_VIDEO_CODE_BLOCK_PATTERN[] = {
2055 {1 << 1, 0}, {2 << 1, 0}, // 0: x
2056 {3 << 1, 0}, {4 << 1, 0}, // 1: 0x
2057 {5 << 1, 0}, {6 << 1, 0}, // 2: 1x
2058 {7 << 1, 0}, {8 << 1, 0}, // 3: 00x
2059 {9 << 1, 0}, {10 << 1, 0}, // 4: 01x
2060 {11 << 1, 0}, {12 << 1, 0}, // 5: 10x
2061 {13 << 1, 0}, {0, 60}, // 6: 11x
2062 {14 << 1, 0}, {15 << 1, 0}, // 7: 000x
2063 {16 << 1, 0}, {17 << 1, 0}, // 8: 001x
2064 {18 << 1, 0}, {19 << 1, 0}, // 9: 010x
2065 {20 << 1, 0}, {21 << 1, 0}, // 10: 011x
2066 {22 << 1, 0}, {23 << 1, 0}, // 11: 100x
2067 {0, 32}, {0, 16}, // 12: 101x
2068 {0, 8}, {0, 4}, // 13: 110x
2069 {24 << 1, 0}, {25 << 1, 0}, // 14: 0000x
2070 {26 << 1, 0}, {27 << 1, 0}, // 15: 0001x
2071 {28 << 1, 0}, {29 << 1, 0}, // 16: 0010x
2072 {30 << 1, 0}, {31 << 1, 0}, // 17: 0011x
2073 {0, 62}, {0, 2}, // 18: 0100x
2074 {0, 61}, {0, 1}, // 19: 0101x
2075 {0, 56}, {0, 52}, // 20: 0110x
2076 {0, 44}, {0, 28}, // 21: 0111x
2077 {0, 40}, {0, 20}, // 22: 1000x
2078 {0, 48}, {0, 12}, // 23: 1001x
2079 {32 << 1, 0}, {33 << 1, 0}, // 24: 0000 0x
2080 {34 << 1, 0}, {35 << 1, 0}, // 25: 0000 1x
2081 {36 << 1, 0}, {37 << 1, 0}, // 26: 0001 0x
2082 {38 << 1, 0}, {39 << 1, 0}, // 27: 0001 1x
2083 {40 << 1, 0}, {41 << 1, 0}, // 28: 0010 0x
2084 {42 << 1, 0}, {43 << 1, 0}, // 29: 0010 1x
2085 {0, 63}, {0, 3}, // 30: 0011 0x
2086 {0, 36}, {0, 24}, // 31: 0011 1x
2087 {44 << 1, 0}, {45 << 1, 0}, // 32: 0000 00x
2088 {46 << 1, 0}, {47 << 1, 0}, // 33: 0000 01x
2089 {48 << 1, 0}, {49 << 1, 0}, // 34: 0000 10x
2090 {50 << 1, 0}, {51 << 1, 0}, // 35: 0000 11x
2091 {52 << 1, 0}, {53 << 1, 0}, // 36: 0001 00x
2092 {54 << 1, 0}, {55 << 1, 0}, // 37: 0001 01x
2093 {56 << 1, 0}, {57 << 1, 0}, // 38: 0001 10x
2094 {58 << 1, 0}, {59 << 1, 0}, // 39: 0001 11x
2095 {0, 34}, {0, 18}, // 40: 0010 00x
2096 {0, 10}, {0, 6}, // 41: 0010 01x
2097 {0, 33}, {0, 17}, // 42: 0010 10x
2098 {0, 9}, {0, 5}, // 43: 0010 11x
2099 {-1, 0}, {60 << 1, 0}, // 44: 0000 000x
2100 {61 << 1, 0}, {62 << 1, 0}, // 45: 0000 001x
2101 {0, 58}, {0, 54}, // 46: 0000 010x
2102 {0, 46}, {0, 30}, // 47: 0000 011x
2103 {0, 57}, {0, 53}, // 48: 0000 100x
2104 {0, 45}, {0, 29}, // 49: 0000 101x
2105 {0, 38}, {0, 26}, // 50: 0000 110x
2106 {0, 37}, {0, 25}, // 51: 0000 111x
2107 {0, 43}, {0, 23}, // 52: 0001 000x
2108 {0, 51}, {0, 15}, // 53: 0001 001x
2109 {0, 42}, {0, 22}, // 54: 0001 010x
2110 {0, 50}, {0, 14}, // 55: 0001 011x
2111 {0, 41}, {0, 21}, // 56: 0001 100x
2112 {0, 49}, {0, 13}, // 57: 0001 101x
2113 {0, 35}, {0, 19}, // 58: 0001 110x
2114 {0, 11}, {0, 7}, // 59: 0001 111x
2115 {0, 39}, {0, 27}, // 60: 0000 0001x
2116 {0, 59}, {0, 55}, // 61: 0000 0010x
2117 {0, 47}, {0, 31}, // 62: 0000 0011x
2118};
2119
2120static const plm_vlc_t PLM_VIDEO_MOTION[] = {
2121 {1 << 1, 0}, {0, 0}, // 0: x
2122 {2 << 1, 0}, {3 << 1, 0}, // 1: 0x
2123 {4 << 1, 0}, {5 << 1, 0}, // 2: 00x
2124 {0, 1}, {0, -1}, // 3: 01x
2125 {6 << 1, 0}, {7 << 1, 0}, // 4: 000x
2126 {0, 2}, {0, -2}, // 5: 001x
2127 {8 << 1, 0}, {9 << 1, 0}, // 6: 0000x
2128 {0, 3}, {0, -3}, // 7: 0001x
2129 {10 << 1, 0}, {11 << 1, 0}, // 8: 0000 0x
2130 {12 << 1, 0}, {13 << 1, 0}, // 9: 0000 1x
2131 {-1, 0}, {14 << 1, 0}, // 10: 0000 00x
2132 {15 << 1, 0}, {16 << 1, 0}, // 11: 0000 01x
2133 {17 << 1, 0}, {18 << 1, 0}, // 12: 0000 10x
2134 {0, 4}, {0, -4}, // 13: 0000 11x
2135 {-1, 0}, {19 << 1, 0}, // 14: 0000 001x
2136 {20 << 1, 0}, {21 << 1, 0}, // 15: 0000 010x
2137 {0, 7}, {0, -7}, // 16: 0000 011x
2138 {0, 6}, {0, -6}, // 17: 0000 100x
2139 {0, 5}, {0, -5}, // 18: 0000 101x
2140 {22 << 1, 0}, {23 << 1, 0}, // 19: 0000 0011x
2141 {24 << 1, 0}, {25 << 1, 0}, // 20: 0000 0100x
2142 {26 << 1, 0}, {27 << 1, 0}, // 21: 0000 0101x
2143 {28 << 1, 0}, {29 << 1, 0}, // 22: 0000 0011 0x
2144 {30 << 1, 0}, {31 << 1, 0}, // 23: 0000 0011 1x
2145 {32 << 1, 0}, {33 << 1, 0}, // 24: 0000 0100 0x
2146 {0, 10}, {0, -10}, // 25: 0000 0100 1x
2147 {0, 9}, {0, -9}, // 26: 0000 0101 0x
2148 {0, 8}, {0, -8}, // 27: 0000 0101 1x
2149 {0, 16}, {0, -16}, // 28: 0000 0011 00x
2150 {0, 15}, {0, -15}, // 29: 0000 0011 01x
2151 {0, 14}, {0, -14}, // 30: 0000 0011 10x
2152 {0, 13}, {0, -13}, // 31: 0000 0011 11x
2153 {0, 12}, {0, -12}, // 32: 0000 0100 00x
2154 {0, 11}, {0, -11}, // 33: 0000 0100 01x
2155};
2156
2157static const plm_vlc_t PLM_VIDEO_DCT_SIZE_LUMINANCE[] = {
2158 {1 << 1, 0}, {2 << 1, 0}, // 0: x
2159 {0, 1}, {0, 2}, // 1: 0x
2160 {3 << 1, 0}, {4 << 1, 0}, // 2: 1x
2161 {0, 0}, {0, 3}, // 3: 10x
2162 {0, 4}, {5 << 1, 0}, // 4: 11x
2163 {0, 5}, {6 << 1, 0}, // 5: 111x
2164 {0, 6}, {7 << 1, 0}, // 6: 1111x
2165 {0, 7}, {8 << 1, 0}, // 7: 1111 1x
2166 {0, 8}, {-1, 0}, // 8: 1111 11x
2167};
2168
2169static const plm_vlc_t PLM_VIDEO_DCT_SIZE_CHROMINANCE[] = {
2170 {1 << 1, 0}, {2 << 1, 0}, // 0: x
2171 {0, 0}, {0, 1}, // 1: 0x
2172 {0, 2}, {3 << 1, 0}, // 2: 1x
2173 {0, 3}, {4 << 1, 0}, // 3: 11x
2174 {0, 4}, {5 << 1, 0}, // 4: 111x
2175 {0, 5}, {6 << 1, 0}, // 5: 1111x
2176 {0, 6}, {7 << 1, 0}, // 6: 1111 1x
2177 {0, 7}, {8 << 1, 0}, // 7: 1111 11x
2178 {0, 8}, {-1, 0}, // 8: 1111 111x
2179};
2180
2181static const plm_vlc_t *PLM_VIDEO_DCT_SIZE[] = {PLM_VIDEO_DCT_SIZE_LUMINANCE, PLM_VIDEO_DCT_SIZE_CHROMINANCE,
2182 PLM_VIDEO_DCT_SIZE_CHROMINANCE};
2183
2184// dct_coeff bitmap:
2185// 0xff00 run
2186// 0x00ff level
2187
2188// Decoded values are unsigned. Sign bit follows in the stream.
2189
2190static const plm_vlc_uint_t PLM_VIDEO_DCT_COEFF[] = {
2191 {1 << 1, 0}, {0, 0x0001}, // 0: x
2192 {2 << 1, 0}, {3 << 1, 0}, // 1: 0x
2193 {4 << 1, 0}, {5 << 1, 0}, // 2: 00x
2194 {6 << 1, 0}, {0, 0x0101}, // 3: 01x
2195 {7 << 1, 0}, {8 << 1, 0}, // 4: 000x
2196 {9 << 1, 0}, {10 << 1, 0}, // 5: 001x
2197 {0, 0x0002}, {0, 0x0201}, // 6: 010x
2198 {11 << 1, 0}, {12 << 1, 0}, // 7: 0000x
2199 {13 << 1, 0}, {14 << 1, 0}, // 8: 0001x
2200 {15 << 1, 0}, {0, 0x0003}, // 9: 0010x
2201 {0, 0x0401}, {0, 0x0301}, // 10: 0011x
2202 {16 << 1, 0}, {0, 0xffff}, // 11: 0000 0x
2203 {17 << 1, 0}, {18 << 1, 0}, // 12: 0000 1x
2204 {0, 0x0701}, {0, 0x0601}, // 13: 0001 0x
2205 {0, 0x0102}, {0, 0x0501}, // 14: 0001 1x
2206 {19 << 1, 0}, {20 << 1, 0}, // 15: 0010 0x
2207 {21 << 1, 0}, {22 << 1, 0}, // 16: 0000 00x
2208 {0, 0x0202}, {0, 0x0901}, // 17: 0000 10x
2209 {0, 0x0004}, {0, 0x0801}, // 18: 0000 11x
2210 {23 << 1, 0}, {24 << 1, 0}, // 19: 0010 00x
2211 {25 << 1, 0}, {26 << 1, 0}, // 20: 0010 01x
2212 {27 << 1, 0}, {28 << 1, 0}, // 21: 0000 000x
2213 {29 << 1, 0}, {30 << 1, 0}, // 22: 0000 001x
2214 {0, 0x0d01}, {0, 0x0006}, // 23: 0010 000x
2215 {0, 0x0c01}, {0, 0x0b01}, // 24: 0010 001x
2216 {0, 0x0302}, {0, 0x0103}, // 25: 0010 010x
2217 {0, 0x0005}, {0, 0x0a01}, // 26: 0010 011x
2218 {31 << 1, 0}, {32 << 1, 0}, // 27: 0000 0000x
2219 {33 << 1, 0}, {34 << 1, 0}, // 28: 0000 0001x
2220 {35 << 1, 0}, {36 << 1, 0}, // 29: 0000 0010x
2221 {37 << 1, 0}, {38 << 1, 0}, // 30: 0000 0011x
2222 {39 << 1, 0}, {40 << 1, 0}, // 31: 0000 0000 0x
2223 {41 << 1, 0}, {42 << 1, 0}, // 32: 0000 0000 1x
2224 {43 << 1, 0}, {44 << 1, 0}, // 33: 0000 0001 0x
2225 {45 << 1, 0}, {46 << 1, 0}, // 34: 0000 0001 1x
2226 {0, 0x1001}, {0, 0x0502}, // 35: 0000 0010 0x
2227 {0, 0x0007}, {0, 0x0203}, // 36: 0000 0010 1x
2228 {0, 0x0104}, {0, 0x0f01}, // 37: 0000 0011 0x
2229 {0, 0x0e01}, {0, 0x0402}, // 38: 0000 0011 1x
2230 {47 << 1, 0}, {48 << 1, 0}, // 39: 0000 0000 00x
2231 {49 << 1, 0}, {50 << 1, 0}, // 40: 0000 0000 01x
2232 {51 << 1, 0}, {52 << 1, 0}, // 41: 0000 0000 10x
2233 {53 << 1, 0}, {54 << 1, 0}, // 42: 0000 0000 11x
2234 {55 << 1, 0}, {56 << 1, 0}, // 43: 0000 0001 00x
2235 {57 << 1, 0}, {58 << 1, 0}, // 44: 0000 0001 01x
2236 {59 << 1, 0}, {60 << 1, 0}, // 45: 0000 0001 10x
2237 {61 << 1, 0}, {62 << 1, 0}, // 46: 0000 0001 11x
2238 {-1, 0}, {63 << 1, 0}, // 47: 0000 0000 000x
2239 {64 << 1, 0}, {65 << 1, 0}, // 48: 0000 0000 001x
2240 {66 << 1, 0}, {67 << 1, 0}, // 49: 0000 0000 010x
2241 {68 << 1, 0}, {69 << 1, 0}, // 50: 0000 0000 011x
2242 {70 << 1, 0}, {71 << 1, 0}, // 51: 0000 0000 100x
2243 {72 << 1, 0}, {73 << 1, 0}, // 52: 0000 0000 101x
2244 {74 << 1, 0}, {75 << 1, 0}, // 53: 0000 0000 110x
2245 {76 << 1, 0}, {77 << 1, 0}, // 54: 0000 0000 111x
2246 {0, 0x000b}, {0, 0x0802}, // 55: 0000 0001 000x
2247 {0, 0x0403}, {0, 0x000a}, // 56: 0000 0001 001x
2248 {0, 0x0204}, {0, 0x0702}, // 57: 0000 0001 010x
2249 {0, 0x1501}, {0, 0x1401}, // 58: 0000 0001 011x
2250 {0, 0x0009}, {0, 0x1301}, // 59: 0000 0001 100x
2251 {0, 0x1201}, {0, 0x0105}, // 60: 0000 0001 101x
2252 {0, 0x0303}, {0, 0x0008}, // 61: 0000 0001 110x
2253 {0, 0x0602}, {0, 0x1101}, // 62: 0000 0001 111x
2254 {78 << 1, 0}, {79 << 1, 0}, // 63: 0000 0000 0001x
2255 {80 << 1, 0}, {81 << 1, 0}, // 64: 0000 0000 0010x
2256 {82 << 1, 0}, {83 << 1, 0}, // 65: 0000 0000 0011x
2257 {84 << 1, 0}, {85 << 1, 0}, // 66: 0000 0000 0100x
2258 {86 << 1, 0}, {87 << 1, 0}, // 67: 0000 0000 0101x
2259 {88 << 1, 0}, {89 << 1, 0}, // 68: 0000 0000 0110x
2260 {90 << 1, 0}, {91 << 1, 0}, // 69: 0000 0000 0111x
2261 {0, 0x0a02}, {0, 0x0902}, // 70: 0000 0000 1000x
2262 {0, 0x0503}, {0, 0x0304}, // 71: 0000 0000 1001x
2263 {0, 0x0205}, {0, 0x0107}, // 72: 0000 0000 1010x
2264 {0, 0x0106}, {0, 0x000f}, // 73: 0000 0000 1011x
2265 {0, 0x000e}, {0, 0x000d}, // 74: 0000 0000 1100x
2266 {0, 0x000c}, {0, 0x1a01}, // 75: 0000 0000 1101x
2267 {0, 0x1901}, {0, 0x1801}, // 76: 0000 0000 1110x
2268 {0, 0x1701}, {0, 0x1601}, // 77: 0000 0000 1111x
2269 {92 << 1, 0}, {93 << 1, 0}, // 78: 0000 0000 0001 0x
2270 {94 << 1, 0}, {95 << 1, 0}, // 79: 0000 0000 0001 1x
2271 {96 << 1, 0}, {97 << 1, 0}, // 80: 0000 0000 0010 0x
2272 {98 << 1, 0}, {99 << 1, 0}, // 81: 0000 0000 0010 1x
2273 {100 << 1, 0}, {101 << 1, 0}, // 82: 0000 0000 0011 0x
2274 {102 << 1, 0}, {103 << 1, 0}, // 83: 0000 0000 0011 1x
2275 {0, 0x001f}, {0, 0x001e}, // 84: 0000 0000 0100 0x
2276 {0, 0x001d}, {0, 0x001c}, // 85: 0000 0000 0100 1x
2277 {0, 0x001b}, {0, 0x001a}, // 86: 0000 0000 0101 0x
2278 {0, 0x0019}, {0, 0x0018}, // 87: 0000 0000 0101 1x
2279 {0, 0x0017}, {0, 0x0016}, // 88: 0000 0000 0110 0x
2280 {0, 0x0015}, {0, 0x0014}, // 89: 0000 0000 0110 1x
2281 {0, 0x0013}, {0, 0x0012}, // 90: 0000 0000 0111 0x
2282 {0, 0x0011}, {0, 0x0010}, // 91: 0000 0000 0111 1x
2283 {104 << 1, 0}, {105 << 1, 0}, // 92: 0000 0000 0001 00x
2284 {106 << 1, 0}, {107 << 1, 0}, // 93: 0000 0000 0001 01x
2285 {108 << 1, 0}, {109 << 1, 0}, // 94: 0000 0000 0001 10x
2286 {110 << 1, 0}, {111 << 1, 0}, // 95: 0000 0000 0001 11x
2287 {0, 0x0028}, {0, 0x0027}, // 96: 0000 0000 0010 00x
2288 {0, 0x0026}, {0, 0x0025}, // 97: 0000 0000 0010 01x
2289 {0, 0x0024}, {0, 0x0023}, // 98: 0000 0000 0010 10x
2290 {0, 0x0022}, {0, 0x0021}, // 99: 0000 0000 0010 11x
2291 {0, 0x0020}, {0, 0x010e}, // 100: 0000 0000 0011 00x
2292 {0, 0x010d}, {0, 0x010c}, // 101: 0000 0000 0011 01x
2293 {0, 0x010b}, {0, 0x010a}, // 102: 0000 0000 0011 10x
2294 {0, 0x0109}, {0, 0x0108}, // 103: 0000 0000 0011 11x
2295 {0, 0x0112}, {0, 0x0111}, // 104: 0000 0000 0001 000x
2296 {0, 0x0110}, {0, 0x010f}, // 105: 0000 0000 0001 001x
2297 {0, 0x0603}, {0, 0x1002}, // 106: 0000 0000 0001 010x
2298 {0, 0x0f02}, {0, 0x0e02}, // 107: 0000 0000 0001 011x
2299 {0, 0x0d02}, {0, 0x0c02}, // 108: 0000 0000 0001 100x
2300 {0, 0x0b02}, {0, 0x1f01}, // 109: 0000 0000 0001 101x
2301 {0, 0x1e01}, {0, 0x1d01}, // 110: 0000 0000 0001 110x
2302 {0, 0x1c01}, {0, 0x1b01}, // 111: 0000 0000 0001 111x
2303};
2304
2305typedef struct {
2306 int full_px;
2307 int is_set;
2308 int r_size;
2309 int h;
2310 int v;
2311} plm_video_motion_t;
2312
2313struct plm_video_t {
2314 double framerate;
2315 double time;
2316 int frames_decoded;
2317 int width;
2318 int height;
2319 int mb_width;
2320 int mb_height;
2321 int mb_size;
2322
2323 int luma_width;
2324 int luma_height;
2325
2326 int chroma_width;
2327 int chroma_height;
2328
2329 int start_code;
2330 int picture_type;
2331
2332 plm_video_motion_t motion_forward;
2333 plm_video_motion_t motion_backward;
2334
2335 int has_sequence_header;
2336
2337 int quantizer_scale;
2338 int slice_begin;
2339 int macroblock_address;
2340
2341 int mb_row;
2342 int mb_col;
2343
2344 int macroblock_type;
2345 int macroblock_intra;
2346
2347 int dc_predictor[3];
2348
2349 plm_buffer_t *buffer;
2350 int destroy_buffer_when_done;
2351
2352 plm_frame_t frame_current;
2353 plm_frame_t frame_forward;
2354 plm_frame_t frame_backward;
2355
2356 uint8_t *frames_data;
2357
2358 int block_data[64];
2359 uint8_t intra_quant_matrix[64];
2360 uint8_t non_intra_quant_matrix[64];
2361
2362 int has_reference_frame;
2363 int assume_no_b_frames;
2364};
2365
2366static inline uint8_t plm_clamp(int n) {
2367 if (n > 255) {
2368 n = 255;
2369 } else if (n < 0) {
2370 n = 0;
2371 }
2372 return n;
2373}
2374
2375int plm_video_decode_sequence_header(plm_video_t *self);
2376void plm_video_init_frame(plm_video_t *self, plm_frame_t *frame, uint8_t *base);
2377void plm_video_decode_picture(plm_video_t *self);
2378void plm_video_decode_slice(plm_video_t *self, int slice);
2379void plm_video_decode_macroblock(plm_video_t *self);
2380void plm_video_decode_motion_vectors(plm_video_t *self);
2381int plm_video_decode_motion_vector(plm_video_t *self, int r_size, int motion);
2382void plm_video_predict_macroblock(plm_video_t *self);
2383void plm_video_copy_macroblock(plm_video_t *self, plm_frame_t *s, int motion_h, int motion_v);
2384void plm_video_interpolate_macroblock(plm_video_t *self, plm_frame_t *s, int motion_h, int motion_v);
2385void plm_video_process_macroblock(plm_video_t *self, uint8_t *s, uint8_t *d, int mh, int mb, int bs, int interp);
2386void plm_video_decode_block(plm_video_t *self, int block);
2387void plm_video_idct(int *block);
2388
2389plm_video_t *plm_video_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done) {
2390 plm_video_t *self = (plm_video_t *)PLM_MALLOC(sizeof(plm_video_t));
2391 memset(self, 0, sizeof(plm_video_t));
2392
2393 self->buffer = buffer;
2394 self->destroy_buffer_when_done = destroy_when_done;
2395
2396 // Attempt to decode the sequence header
2397 self->start_code = plm_buffer_find_start_code(self->buffer, PLM_START_SEQUENCE);
2398 if (self->start_code != -1) {
2399 plm_video_decode_sequence_header(self);
2400 }
2401 return self;
2402}
2403
2404void plm_video_destroy(plm_video_t *self) {
2405 if (self->destroy_buffer_when_done) {
2406 plm_buffer_destroy(self->buffer);
2407 }
2408
2409 if (self->has_sequence_header) {
2410 PLM_FREE(self->frames_data);
2411 }
2412
2413 PLM_FREE(self);
2414}
2415
2416double plm_video_get_framerate(plm_video_t *self) { return plm_video_has_header(self) ? self->framerate : 0; }
2417
2418int plm_video_get_width(plm_video_t *self) { return plm_video_has_header(self) ? self->width : 0; }
2419
2420int plm_video_get_height(plm_video_t *self) { return plm_video_has_header(self) ? self->height : 0; }
2421
2422void plm_video_set_no_delay(plm_video_t *self, int no_delay) { self->assume_no_b_frames = no_delay; }
2423
2424double plm_video_get_time(plm_video_t *self) { return self->time; }
2425
2426void plm_video_set_time(plm_video_t *self, double time) {
2427 self->frames_decoded = self->framerate * time;
2428 self->time = time;
2429}
2430
2431void plm_video_rewind(plm_video_t *self) {
2432 plm_buffer_rewind(self->buffer);
2433 self->time = 0;
2434 self->frames_decoded = 0;
2435 self->has_reference_frame = FALSE;
2436 self->start_code = -1;
2437}
2438
2439int plm_video_has_ended(plm_video_t *self) { return plm_buffer_has_ended(self->buffer); }
2440
2441plm_frame_t *plm_video_decode(plm_video_t *self) {
2442 if (!plm_video_has_header(self)) {
2443 return NULL;
2444 }
2445
2446 plm_frame_t *frame = NULL;
2447 do {
2448 if (self->start_code != PLM_START_PICTURE) {
2449 self->start_code = plm_buffer_find_start_code(self->buffer, PLM_START_PICTURE);
2450
2451 if (self->start_code == -1) {
2452 // If we reached the end of the file and the previously decoded
2453 // frame was a reference frame, we still have to return it.
2454 if (self->has_reference_frame && !self->assume_no_b_frames && plm_buffer_has_ended(self->buffer) &&
2455 (self->picture_type == PLM_VIDEO_PICTURE_TYPE_INTRA ||
2456 self->picture_type == PLM_VIDEO_PICTURE_TYPE_PREDICTIVE)) {
2457 self->has_reference_frame = FALSE;
2458 frame = &self->frame_backward;
2459 break;
2460 }
2461
2462 return NULL;
2463 }
2464 }
2465
2466 // Make sure we have a full picture in the buffer before attempting to
2467 // decode it. Sadly, this can only be done by seeking for the start code
2468 // of the next picture. Also, if we didn't find the start code for the
2469 // next picture, but the source has ended, we assume that this last
2470 // picture is in the buffer.
2471 if (plm_buffer_has_start_code(self->buffer, PLM_START_PICTURE) == -1 && !plm_buffer_has_ended(self->buffer)) {
2472 return NULL;
2473 }
2474 plm_buffer_discard_read_bytes(self->buffer);
2475
2476 plm_video_decode_picture(self);
2477
2478 if (self->assume_no_b_frames) {
2479 frame = &self->frame_backward;
2480 } else if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_B) {
2481 frame = &self->frame_current;
2482 } else if (self->has_reference_frame) {
2483 frame = &self->frame_forward;
2484 } else {
2485 self->has_reference_frame = TRUE;
2486 }
2487 } while (!frame);
2488
2489 frame->time = self->time;
2490 self->frames_decoded++;
2491 self->time = (double)self->frames_decoded / self->framerate;
2492
2493 return frame;
2494}
2495
2496int plm_video_has_header(plm_video_t *self) {
2497 if (self->has_sequence_header) {
2498 return TRUE;
2499 }
2500
2501 if (self->start_code != PLM_START_SEQUENCE) {
2502 self->start_code = plm_buffer_find_start_code(self->buffer, PLM_START_SEQUENCE);
2503 }
2504 if (self->start_code == -1) {
2505 return FALSE;
2506 }
2507
2508 if (!plm_video_decode_sequence_header(self)) {
2509 return FALSE;
2510 }
2511
2512 return TRUE;
2513}
2514
2515int plm_video_decode_sequence_header(plm_video_t *self) {
2516 int max_header_size = 64 + 2 * 64 * 8; // 64 bit header + 2x 64 byte matrix
2517 if (!plm_buffer_has(self->buffer, max_header_size)) {
2518 return FALSE;
2519 }
2520
2521 self->width = plm_buffer_read(self->buffer, 12);
2522 self->height = plm_buffer_read(self->buffer, 12);
2523
2524 if (self->width <= 0 || self->height <= 0) {
2525 return FALSE;
2526 }
2527
2528 // Skip pixel aspect ratio
2529 plm_buffer_skip(self->buffer, 4);
2530
2531 self->framerate = PLM_VIDEO_PICTURE_RATE[plm_buffer_read(self->buffer, 4)];
2532
2533 // Skip bit_rate, marker, buffer_size and constrained bit
2534 plm_buffer_skip(self->buffer, 18 + 1 + 10 + 1);
2535
2536 // Load custom intra quant matrix?
2537 if (plm_buffer_read(self->buffer, 1)) {
2538 for (int i = 0; i < 64; i++) {
2539 int idx = PLM_VIDEO_ZIG_ZAG[i];
2540 self->intra_quant_matrix[idx] = plm_buffer_read(self->buffer, 8);
2541 }
2542 } else {
2543 memcpy(self->intra_quant_matrix, PLM_VIDEO_INTRA_QUANT_MATRIX, 64);
2544 }
2545
2546 // Load custom non intra quant matrix?
2547 if (plm_buffer_read(self->buffer, 1)) {
2548 for (int i = 0; i < 64; i++) {
2549 int idx = PLM_VIDEO_ZIG_ZAG[i];
2550 self->non_intra_quant_matrix[idx] = plm_buffer_read(self->buffer, 8);
2551 }
2552 } else {
2553 memcpy(self->non_intra_quant_matrix, PLM_VIDEO_NON_INTRA_QUANT_MATRIX, 64);
2554 }
2555
2556 self->mb_width = (self->width + 15) >> 4;
2557 self->mb_height = (self->height + 15) >> 4;
2558 self->mb_size = self->mb_width * self->mb_height;
2559
2560 self->luma_width = self->mb_width << 4;
2561 self->luma_height = self->mb_height << 4;
2562
2563 self->chroma_width = self->mb_width << 3;
2564 self->chroma_height = self->mb_height << 3;
2565
2566 // Allocate one big chunk of data for all 3 frames = 9 planes
2567 size_t luma_plane_size = self->luma_width * self->luma_height;
2568 size_t chroma_plane_size = self->chroma_width * self->chroma_height;
2569 size_t frame_data_size = (luma_plane_size + 2 * chroma_plane_size);
2570
2571 self->frames_data = (uint8_t *)PLM_MALLOC(frame_data_size * 3);
2572 plm_video_init_frame(self, &self->frame_current, self->frames_data + frame_data_size * 0);
2573 plm_video_init_frame(self, &self->frame_forward, self->frames_data + frame_data_size * 1);
2574 plm_video_init_frame(self, &self->frame_backward, self->frames_data + frame_data_size * 2);
2575
2576 self->has_sequence_header = TRUE;
2577 return TRUE;
2578}
2579
2580void plm_video_init_frame(plm_video_t *self, plm_frame_t *frame, uint8_t *base) {
2581 size_t luma_plane_size = self->luma_width * self->luma_height;
2582 size_t chroma_plane_size = self->chroma_width * self->chroma_height;
2583
2584 frame->width = self->width;
2585 frame->height = self->height;
2586 frame->y.width = self->luma_width;
2587 frame->y.height = self->luma_height;
2588 frame->y.data = base;
2589
2590 frame->cr.width = self->chroma_width;
2591 frame->cr.height = self->chroma_height;
2592 frame->cr.data = base + luma_plane_size;
2593
2594 frame->cb.width = self->chroma_width;
2595 frame->cb.height = self->chroma_height;
2596 frame->cb.data = base + luma_plane_size + chroma_plane_size;
2597}
2598
2599void plm_video_decode_picture(plm_video_t *self) {
2600 plm_buffer_skip(self->buffer, 10); // skip temporalReference
2601 self->picture_type = plm_buffer_read(self->buffer, 3);
2602 plm_buffer_skip(self->buffer, 16); // skip vbv_delay
2603
2604 // D frames or unknown coding type
2605 if (self->picture_type <= 0 || self->picture_type > PLM_VIDEO_PICTURE_TYPE_B) {
2606 return;
2607 }
2608
2609 // Forward full_px, f_code
2610 if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_PREDICTIVE || self->picture_type == PLM_VIDEO_PICTURE_TYPE_B) {
2611 self->motion_forward.full_px = plm_buffer_read(self->buffer, 1);
2612 int f_code = plm_buffer_read(self->buffer, 3);
2613 if (f_code == 0) {
2614 // Ignore picture with zero f_code
2615 return;
2616 }
2617 self->motion_forward.r_size = f_code - 1;
2618 }
2619
2620 // Backward full_px, f_code
2621 if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_B) {
2622 self->motion_backward.full_px = plm_buffer_read(self->buffer, 1);
2623 int f_code = plm_buffer_read(self->buffer, 3);
2624 if (f_code == 0) {
2625 // Ignore picture with zero f_code
2626 return;
2627 }
2628 self->motion_backward.r_size = f_code - 1;
2629 }
2630
2631 plm_frame_t frame_temp = self->frame_forward;
2632 if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_INTRA || self->picture_type == PLM_VIDEO_PICTURE_TYPE_PREDICTIVE) {
2633 self->frame_forward = self->frame_backward;
2634 }
2635
2636 // Find first slice start code; skip extension and user data
2637 do {
2638 self->start_code = plm_buffer_next_start_code(self->buffer);
2639 } while (self->start_code == PLM_START_EXTENSION || self->start_code == PLM_START_USER_DATA);
2640
2641 // Decode all slices
2642 while (PLM_START_IS_SLICE(self->start_code)) {
2643 plm_video_decode_slice(self, self->start_code & 0x000000FF);
2644 if (self->macroblock_address >= self->mb_size - 2) {
2645 break;
2646 }
2647 self->start_code = plm_buffer_next_start_code(self->buffer);
2648 }
2649
2650 // If this is a reference picture rotate the prediction pointers
2651 if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_INTRA || self->picture_type == PLM_VIDEO_PICTURE_TYPE_PREDICTIVE) {
2652 self->frame_backward = self->frame_current;
2653 self->frame_current = frame_temp;
2654 }
2655}
2656
2657void plm_video_decode_slice(plm_video_t *self, int slice) {
2658 self->slice_begin = TRUE;
2659 self->macroblock_address = (slice - 1) * self->mb_width - 1;
2660
2661 // Reset motion vectors and DC predictors
2662 self->motion_backward.h = self->motion_forward.h = 0;
2663 self->motion_backward.v = self->motion_forward.v = 0;
2664 self->dc_predictor[0] = 128;
2665 self->dc_predictor[1] = 128;
2666 self->dc_predictor[2] = 128;
2667
2668 self->quantizer_scale = plm_buffer_read(self->buffer, 5);
2669
2670 // Skip extra
2671 while (plm_buffer_read(self->buffer, 1)) {
2672 plm_buffer_skip(self->buffer, 8);
2673 }
2674
2675 do {
2676 plm_video_decode_macroblock(self);
2677 } while (self->macroblock_address < self->mb_size - 1 && plm_buffer_peek_non_zero(self->buffer, 23));
2678}
2679
2680void plm_video_decode_macroblock(plm_video_t *self) {
2681 // Decode increment
2682 int increment = 0;
2683 int t = plm_buffer_read_vlc(self->buffer, PLM_VIDEO_MACROBLOCK_ADDRESS_INCREMENT);
2684
2685 while (t == 34) {
2686 // macroblock_stuffing
2687 t = plm_buffer_read_vlc(self->buffer, PLM_VIDEO_MACROBLOCK_ADDRESS_INCREMENT);
2688 }
2689 while (t == 35) {
2690 // macroblock_escape
2691 increment += 33;
2692 t = plm_buffer_read_vlc(self->buffer, PLM_VIDEO_MACROBLOCK_ADDRESS_INCREMENT);
2693 }
2694 increment += t;
2695
2696 // Process any skipped macroblocks
2697 if (self->slice_begin) {
2698 // The first increment of each slice is relative to beginning of the
2699 // previous row, not the previous macroblock
2700 self->slice_begin = FALSE;
2701 self->macroblock_address += increment;
2702 } else {
2703 if (self->macroblock_address + increment >= self->mb_size) {
2704 return; // invalid
2705 }
2706 if (increment > 1) {
2707 // Skipped macroblocks reset DC predictors
2708 self->dc_predictor[0] = 128;
2709 self->dc_predictor[1] = 128;
2710 self->dc_predictor[2] = 128;
2711
2712 // Skipped macroblocks in P-pictures reset motion vectors
2713 if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_PREDICTIVE) {
2714 self->motion_forward.h = 0;
2715 self->motion_forward.v = 0;
2716 }
2717 }
2718
2719 // Predict skipped macroblocks
2720 while (increment > 1) {
2721 self->macroblock_address++;
2722 self->mb_row = self->macroblock_address / self->mb_width;
2723 self->mb_col = self->macroblock_address % self->mb_width;
2724
2725 plm_video_predict_macroblock(self);
2726 increment--;
2727 }
2728 self->macroblock_address++;
2729 }
2730
2731 self->mb_row = self->macroblock_address / self->mb_width;
2732 self->mb_col = self->macroblock_address % self->mb_width;
2733
2734 if (self->mb_col >= self->mb_width || self->mb_row >= self->mb_height) {
2735 return; // corrupt stream;
2736 }
2737
2738 // Process the current macroblock
2739 const plm_vlc_t *table = PLM_VIDEO_MACROBLOCK_TYPE[self->picture_type];
2740 self->macroblock_type = plm_buffer_read_vlc(self->buffer, table);
2741
2742 self->macroblock_intra = (self->macroblock_type & 0x01);
2743 self->motion_forward.is_set = (self->macroblock_type & 0x08);
2744 self->motion_backward.is_set = (self->macroblock_type & 0x04);
2745
2746 // Quantizer scale
2747 if ((self->macroblock_type & 0x10) != 0) {
2748 self->quantizer_scale = plm_buffer_read(self->buffer, 5);
2749 }
2750
2751 if (self->macroblock_intra) {
2752 // Intra-coded macroblocks reset motion vectors
2753 self->motion_backward.h = self->motion_forward.h = 0;
2754 self->motion_backward.v = self->motion_forward.v = 0;
2755 } else {
2756 // Non-intra macroblocks reset DC predictors
2757 self->dc_predictor[0] = 128;
2758 self->dc_predictor[1] = 128;
2759 self->dc_predictor[2] = 128;
2760
2761 plm_video_decode_motion_vectors(self);
2762 plm_video_predict_macroblock(self);
2763 }
2764
2765 // Decode blocks
2766 int cbp = ((self->macroblock_type & 0x02) != 0) ? plm_buffer_read_vlc(self->buffer, PLM_VIDEO_CODE_BLOCK_PATTERN)
2767 : (self->macroblock_intra ? 0x3f : 0);
2768
2769 for (int block = 0, mask = 0x20; block < 6; block++) {
2770 if ((cbp & mask) != 0) {
2771 plm_video_decode_block(self, block);
2772 }
2773 mask >>= 1;
2774 }
2775}
2776
2777void plm_video_decode_motion_vectors(plm_video_t *self) {
2778
2779 // Forward
2780 if (self->motion_forward.is_set) {
2781 int r_size = self->motion_forward.r_size;
2782 self->motion_forward.h = plm_video_decode_motion_vector(self, r_size, self->motion_forward.h);
2783 self->motion_forward.v = plm_video_decode_motion_vector(self, r_size, self->motion_forward.v);
2784 } else if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_PREDICTIVE) {
2785 // No motion information in P-picture, reset vectors
2786 self->motion_forward.h = 0;
2787 self->motion_forward.v = 0;
2788 }
2789
2790 if (self->motion_backward.is_set) {
2791 int r_size = self->motion_backward.r_size;
2792 self->motion_backward.h = plm_video_decode_motion_vector(self, r_size, self->motion_backward.h);
2793 self->motion_backward.v = plm_video_decode_motion_vector(self, r_size, self->motion_backward.v);
2794 }
2795}
2796
2797int plm_video_decode_motion_vector(plm_video_t *self, int r_size, int motion) {
2798 int fscale = 1 << r_size;
2799 int m_code = plm_buffer_read_vlc(self->buffer, PLM_VIDEO_MOTION);
2800 int r = 0;
2801 int d;
2802
2803 if ((m_code != 0) && (fscale != 1)) {
2804 r = plm_buffer_read(self->buffer, r_size);
2805 d = ((abs(m_code) - 1) << r_size) + r + 1;
2806 if (m_code < 0) {
2807 d = -d;
2808 }
2809 } else {
2810 d = m_code;
2811 }
2812
2813 motion += d;
2814 if (motion > (fscale << 4) - 1) {
2815 motion -= fscale << 5;
2816 } else if (motion < ((-fscale) << 4)) {
2817 motion += fscale << 5;
2818 }
2819
2820 return motion;
2821}
2822
2823void plm_video_predict_macroblock(plm_video_t *self) {
2824 int fw_h = self->motion_forward.h;
2825 int fw_v = self->motion_forward.v;
2826
2827 if (self->motion_forward.full_px) {
2828 fw_h <<= 1;
2829 fw_v <<= 1;
2830 }
2831
2832 if (self->picture_type == PLM_VIDEO_PICTURE_TYPE_B) {
2833 int bw_h = self->motion_backward.h;
2834 int bw_v = self->motion_backward.v;
2835
2836 if (self->motion_backward.full_px) {
2837 bw_h <<= 1;
2838 bw_v <<= 1;
2839 }
2840
2841 if (self->motion_forward.is_set) {
2842 plm_video_copy_macroblock(self, &self->frame_forward, fw_h, fw_v);
2843 if (self->motion_backward.is_set) {
2844 plm_video_interpolate_macroblock(self, &self->frame_backward, bw_h, bw_v);
2845 }
2846 } else {
2847 plm_video_copy_macroblock(self, &self->frame_backward, bw_h, bw_v);
2848 }
2849 } else {
2850 plm_video_copy_macroblock(self, &self->frame_forward, fw_h, fw_v);
2851 }
2852}
2853
2854void plm_video_copy_macroblock(plm_video_t *self, plm_frame_t *s, int motion_h, int motion_v) {
2855 plm_frame_t *d = &self->frame_current;
2856 plm_video_process_macroblock(self, s->y.data, d->y.data, motion_h, motion_v, 16, FALSE);
2857 plm_video_process_macroblock(self, s->cr.data, d->cr.data, motion_h / 2, motion_v / 2, 8, FALSE);
2858 plm_video_process_macroblock(self, s->cb.data, d->cb.data, motion_h / 2, motion_v / 2, 8, FALSE);
2859}
2860
2861void plm_video_interpolate_macroblock(plm_video_t *self, plm_frame_t *s, int motion_h, int motion_v) {
2862 plm_frame_t *d = &self->frame_current;
2863 plm_video_process_macroblock(self, s->y.data, d->y.data, motion_h, motion_v, 16, TRUE);
2864 plm_video_process_macroblock(self, s->cr.data, d->cr.data, motion_h / 2, motion_v / 2, 8, TRUE);
2865 plm_video_process_macroblock(self, s->cb.data, d->cb.data, motion_h / 2, motion_v / 2, 8, TRUE);
2866}
2867
2868#define PLM_BLOCK_SET(DEST, DEST_INDEX, DEST_WIDTH, SOURCE_INDEX, SOURCE_WIDTH, BLOCK_SIZE, OP) \
2869 do { \
2870 int dest_scan = DEST_WIDTH - BLOCK_SIZE; \
2871 int source_scan = SOURCE_WIDTH - BLOCK_SIZE; \
2872 for (int y = 0; y < BLOCK_SIZE; y++) { \
2873 for (int x = 0; x < BLOCK_SIZE; x++) { \
2874 DEST[DEST_INDEX] = OP; \
2875 SOURCE_INDEX++; \
2876 DEST_INDEX++; \
2877 } \
2878 SOURCE_INDEX += source_scan; \
2879 DEST_INDEX += dest_scan; \
2880 } \
2881 } while (FALSE)
2882
2883void plm_video_process_macroblock(plm_video_t *self, uint8_t *s, uint8_t *d, int motion_h, int motion_v, int block_size,
2884 int interpolate) {
2885 int dw = self->mb_width * block_size;
2886
2887 int hp = motion_h >> 1;
2888 int vp = motion_v >> 1;
2889 int odd_h = (motion_h & 1) == 1;
2890 int odd_v = (motion_v & 1) == 1;
2891
2892 unsigned int si = ((self->mb_row * block_size) + vp) * dw + (self->mb_col * block_size) + hp;
2893 unsigned int di = (self->mb_row * dw + self->mb_col) * block_size;
2894
2895 unsigned int max_address = (dw * (self->mb_height * block_size - block_size + 1) - block_size);
2896 if (si > max_address || di > max_address) {
2897 return; // corrupt video
2898 }
2899
2900#define PLM_MB_CASE(INTERPOLATE, ODD_H, ODD_V, OP) \
2901 case ((INTERPOLATE << 2) | (ODD_H << 1) | (ODD_V)): \
2902 PLM_BLOCK_SET(d, di, dw, si, dw, block_size, OP); \
2903 break
2904
2905 switch ((interpolate << 2) | (odd_h << 1) | (odd_v)) {
2906 PLM_MB_CASE(0, 0, 0, (s[si]));
2907 PLM_MB_CASE(0, 0, 1, (s[si] + s[si + dw] + 1) >> 1);
2908 PLM_MB_CASE(0, 1, 0, (s[si] + s[si + 1] + 1) >> 1);
2909 PLM_MB_CASE(0, 1, 1, (s[si] + s[si + 1] + s[si + dw] + s[si + dw + 1] + 2) >> 2);
2910
2911 PLM_MB_CASE(1, 0, 0, (d[di] + (s[si]) + 1) >> 1);
2912 PLM_MB_CASE(1, 0, 1, (d[di] + ((s[si] + s[si + dw] + 1) >> 1) + 1) >> 1);
2913 PLM_MB_CASE(1, 1, 0, (d[di] + ((s[si] + s[si + 1] + 1) >> 1) + 1) >> 1);
2914 PLM_MB_CASE(1, 1, 1, (d[di] + ((s[si] + s[si + 1] + s[si + dw] + s[si + dw + 1] + 2) >> 2) + 1) >> 1);
2915 }
2916
2917#undef PLM_MB_CASE
2918}
2919
2920void plm_video_decode_block(plm_video_t *self, int block) {
2921
2922 int n = 0;
2923 uint8_t *quant_matrix;
2924
2925 // Decode DC coefficient of intra-coded blocks
2926 if (self->macroblock_intra) {
2927 int predictor;
2928 int dct_size;
2929
2930 // DC prediction
2931 int plane_index = block > 3 ? block - 3 : 0;
2932 predictor = self->dc_predictor[plane_index];
2933 dct_size = plm_buffer_read_vlc(self->buffer, PLM_VIDEO_DCT_SIZE[plane_index]);
2934
2935 // Read DC coeff
2936 if (dct_size > 0) {
2937 int differential = plm_buffer_read(self->buffer, dct_size);
2938 if ((differential & (1 << (dct_size - 1))) != 0) {
2939 self->block_data[0] = predictor + differential;
2940 } else {
2941 self->block_data[0] = predictor + (-(1 << dct_size) | (differential + 1));
2942 }
2943 } else {
2944 self->block_data[0] = predictor;
2945 }
2946
2947 // Save predictor value
2948 self->dc_predictor[plane_index] = self->block_data[0];
2949
2950 // Dequantize + premultiply
2951 self->block_data[0] <<= (3 + 5);
2952
2953 quant_matrix = self->intra_quant_matrix;
2954 n = 1;
2955 } else {
2956 quant_matrix = self->non_intra_quant_matrix;
2957 }
2958
2959 // Decode AC coefficients (+DC for non-intra)
2960 int level = 0;
2961 while (TRUE) {
2962 int run = 0;
2963 uint16_t coeff = plm_buffer_read_vlc_uint(self->buffer, PLM_VIDEO_DCT_COEFF);
2964
2965 if ((coeff == 0x0001) && (n > 0) && (plm_buffer_read(self->buffer, 1) == 0)) {
2966 // end_of_block
2967 break;
2968 }
2969 if (coeff == 0xffff) {
2970 // escape
2971 run = plm_buffer_read(self->buffer, 6);
2972 level = plm_buffer_read(self->buffer, 8);
2973 if (level == 0) {
2974 level = plm_buffer_read(self->buffer, 8);
2975 } else if (level == 128) {
2976 level = plm_buffer_read(self->buffer, 8) - 256;
2977 } else if (level > 128) {
2978 level = level - 256;
2979 }
2980 } else {
2981 run = coeff >> 8;
2982 level = coeff & 0xff;
2983 if (plm_buffer_read(self->buffer, 1)) {
2984 level = -level;
2985 }
2986 }
2987
2988 n += run;
2989 if (n < 0 || n >= 64) {
2990 return; // invalid
2991 }
2992
2993 int de_zig_zagged = PLM_VIDEO_ZIG_ZAG[n];
2994 n++;
2995
2996 // Dequantize, oddify, clip
2997 level <<= 1;
2998 if (!self->macroblock_intra) {
2999 level += (level < 0 ? -1 : 1);
3000 }
3001 level = (level * self->quantizer_scale * quant_matrix[de_zig_zagged]) >> 4;
3002 if ((level & 1) == 0) {
3003 level -= level > 0 ? 1 : -1;
3004 }
3005 if (level > 2047) {
3006 level = 2047;
3007 } else if (level < -2048) {
3008 level = -2048;
3009 }
3010
3011 // Save premultiplied coefficient
3012 self->block_data[de_zig_zagged] = level * PLM_VIDEO_PREMULTIPLIER_MATRIX[de_zig_zagged];
3013 }
3014
3015 // Move block to its place
3016 uint8_t *d;
3017 int dw;
3018 int di;
3019
3020 if (block < 4) {
3021 d = self->frame_current.y.data;
3022 dw = self->luma_width;
3023 di = (self->mb_row * self->luma_width + self->mb_col) << 4;
3024 if ((block & 1) != 0) {
3025 di += 8;
3026 }
3027 if ((block & 2) != 0) {
3028 di += self->luma_width << 3;
3029 }
3030 } else {
3031 d = (block == 4) ? self->frame_current.cb.data : self->frame_current.cr.data;
3032 dw = self->chroma_width;
3033 di = ((self->mb_row * self->luma_width) << 2) + (self->mb_col << 3);
3034 }
3035
3036 int *s = self->block_data;
3037 int si = 0;
3038 if (self->macroblock_intra) {
3039 // Overwrite (no prediction)
3040 if (n == 1) {
3041 int clamped = plm_clamp((s[0] + 128) >> 8);
3042 PLM_BLOCK_SET(d, di, dw, si, 8, 8, clamped);
3043 s[0] = 0;
3044 } else {
3045 plm_video_idct(s);
3046 PLM_BLOCK_SET(d, di, dw, si, 8, 8, plm_clamp(s[si]));
3047 memset(self->block_data, 0, sizeof(self->block_data));
3048 }
3049 } else {
3050 // Add data to the predicted macroblock
3051 if (n == 1) {
3052 int value = (s[0] + 128) >> 8;
3053 PLM_BLOCK_SET(d, di, dw, si, 8, 8, plm_clamp(d[di] + value));
3054 s[0] = 0;
3055 } else {
3056 plm_video_idct(s);
3057 PLM_BLOCK_SET(d, di, dw, si, 8, 8, plm_clamp(d[di] + s[si]));
3058 memset(self->block_data, 0, sizeof(self->block_data));
3059 }
3060 }
3061}
3062
3063void plm_video_idct(int *block) {
3064 int b1, b3, b4, b6, b7, tmp1, tmp2, m0, x0, x1, x2, x3, x4, y3, y4, y5, y6, y7;
3065
3066 // Transform columns
3067 for (int i = 0; i < 8; ++i) {
3068 b1 = block[4 * 8 + i];
3069 b3 = block[2 * 8 + i] + block[6 * 8 + i];
3070 b4 = block[5 * 8 + i] - block[3 * 8 + i];
3071 tmp1 = block[1 * 8 + i] + block[7 * 8 + i];
3072 tmp2 = block[3 * 8 + i] + block[5 * 8 + i];
3073 b6 = block[1 * 8 + i] - block[7 * 8 + i];
3074 b7 = tmp1 + tmp2;
3075 m0 = block[0 * 8 + i];
3076 x4 = ((b6 * 473 - b4 * 196 + 128) >> 8) - b7;
3077 x0 = x4 - (((tmp1 - tmp2) * 362 + 128) >> 8);
3078 x1 = m0 - b1;
3079 x2 = (((block[2 * 8 + i] - block[6 * 8 + i]) * 362 + 128) >> 8) - b3;
3080 x3 = m0 + b1;
3081 y3 = x1 + x2;
3082 y4 = x3 + b3;
3083 y5 = x1 - x2;
3084 y6 = x3 - b3;
3085 y7 = -x0 - ((b4 * 473 + b6 * 196 + 128) >> 8);
3086 block[0 * 8 + i] = b7 + y4;
3087 block[1 * 8 + i] = x4 + y3;
3088 block[2 * 8 + i] = y5 - x0;
3089 block[3 * 8 + i] = y6 - y7;
3090 block[4 * 8 + i] = y6 + y7;
3091 block[5 * 8 + i] = x0 + y5;
3092 block[6 * 8 + i] = y3 - x4;
3093 block[7 * 8 + i] = y4 - b7;
3094 }
3095
3096 // Transform rows
3097 for (int i = 0; i < 64; i += 8) {
3098 b1 = block[4 + i];
3099 b3 = block[2 + i] + block[6 + i];
3100 b4 = block[5 + i] - block[3 + i];
3101 tmp1 = block[1 + i] + block[7 + i];
3102 tmp2 = block[3 + i] + block[5 + i];
3103 b6 = block[1 + i] - block[7 + i];
3104 b7 = tmp1 + tmp2;
3105 m0 = block[0 + i];
3106 x4 = ((b6 * 473 - b4 * 196 + 128) >> 8) - b7;
3107 x0 = x4 - (((tmp1 - tmp2) * 362 + 128) >> 8);
3108 x1 = m0 - b1;
3109 x2 = (((block[2 + i] - block[6 + i]) * 362 + 128) >> 8) - b3;
3110 x3 = m0 + b1;
3111 y3 = x1 + x2;
3112 y4 = x3 + b3;
3113 y5 = x1 - x2;
3114 y6 = x3 - b3;
3115 y7 = -x0 - ((b4 * 473 + b6 * 196 + 128) >> 8);
3116 block[0 + i] = (b7 + y4 + 128) >> 8;
3117 block[1 + i] = (x4 + y3 + 128) >> 8;
3118 block[2 + i] = (y5 - x0 + 128) >> 8;
3119 block[3 + i] = (y6 - y7 + 128) >> 8;
3120 block[4 + i] = (y6 + y7 + 128) >> 8;
3121 block[5 + i] = (x0 + y5 + 128) >> 8;
3122 block[6 + i] = (y3 - x4 + 128) >> 8;
3123 block[7 + i] = (y4 - b7 + 128) >> 8;
3124 }
3125}
3126
3127// YCbCr conversion following the BT.601 standard:
3128// https://infogalactic.com/info/YCbCr#ITU-R_BT.601_conversion
3129
3130#define PLM_PUT_PIXEL(RI, GI, BI, Y_OFFSET, DEST_OFFSET) \
3131 y = ((frame->y.data[y_index + Y_OFFSET] - 16) * 76309) >> 16; \
3132 dest[d_index + DEST_OFFSET + RI] = plm_clamp(y + r); \
3133 dest[d_index + DEST_OFFSET + GI] = plm_clamp(y - g); \
3134 dest[d_index + DEST_OFFSET + BI] = plm_clamp(y + b);
3135
3136#define PLM_DEFINE_FRAME_CONVERT_FUNCTION(NAME, BYTES_PER_PIXEL, RI, GI, BI) \
3137 void NAME(plm_frame_t *frame, uint8_t *dest, int stride) { \
3138 int cols = frame->width >> 1; \
3139 int rows = frame->height >> 1; \
3140 int yw = frame->y.width; \
3141 int cw = frame->cb.width; \
3142 for (int row = 0; row < rows; row++) { \
3143 int c_index = row * cw; \
3144 int y_index = row * 2 * yw; \
3145 int d_index = row * 2 * stride; \
3146 for (int col = 0; col < cols; col++) { \
3147 int y; \
3148 int cr = frame->cr.data[c_index] - 128; \
3149 int cb = frame->cb.data[c_index] - 128; \
3150 int r = (cr * 104597) >> 16; \
3151 int g = (cb * 25674 + cr * 53278) >> 16; \
3152 int b = (cb * 132201) >> 16; \
3153 PLM_PUT_PIXEL(RI, GI, BI, 0, 0); \
3154 PLM_PUT_PIXEL(RI, GI, BI, 1, BYTES_PER_PIXEL); \
3155 PLM_PUT_PIXEL(RI, GI, BI, yw, stride); \
3156 PLM_PUT_PIXEL(RI, GI, BI, yw + 1, stride + BYTES_PER_PIXEL); \
3157 c_index += 1; \
3158 y_index += 2; \
3159 d_index += 2 * BYTES_PER_PIXEL; \
3160 } \
3161 } \
3162 }
3163
3164PLM_DEFINE_FRAME_CONVERT_FUNCTION(plm_frame_to_rgb, 3, 0, 1, 2)
3165PLM_DEFINE_FRAME_CONVERT_FUNCTION(plm_frame_to_bgr, 3, 2, 1, 0)
3166PLM_DEFINE_FRAME_CONVERT_FUNCTION(plm_frame_to_rgba, 4, 0, 1, 2)
3167PLM_DEFINE_FRAME_CONVERT_FUNCTION(plm_frame_to_bgra, 4, 2, 1, 0)
3168PLM_DEFINE_FRAME_CONVERT_FUNCTION(plm_frame_to_argb, 4, 1, 2, 3)
3169PLM_DEFINE_FRAME_CONVERT_FUNCTION(plm_frame_to_abgr, 4, 3, 2, 1)
3170
3171#undef PLM_PUT_PIXEL
3172#undef PLM_DEFINE_FRAME_CONVERT_FUNCTION
3173
3174// -----------------------------------------------------------------------------
3175// plm_audio implementation
3176
3177// Based on kjmp2 by Martin J. Fiedler
3178// http://keyj.emphy.de/kjmp2/
3179
3180static const int PLM_AUDIO_FRAME_SYNC = 0x7ff;
3181
3182static const int PLM_AUDIO_MPEG_2_5 = 0x0;
3183static const int PLM_AUDIO_MPEG_2 = 0x2;
3184static const int PLM_AUDIO_MPEG_1 = 0x3;
3185
3186static const int PLM_AUDIO_LAYER_III = 0x1;
3187static const int PLM_AUDIO_LAYER_II = 0x2;
3188static const int PLM_AUDIO_LAYER_I = 0x3;
3189
3190static const int PLM_AUDIO_MODE_STEREO = 0x0;
3191static const int PLM_AUDIO_MODE_JOINT_STEREO = 0x1;
3192static const int PLM_AUDIO_MODE_DUAL_CHANNEL = 0x2;
3193static const int PLM_AUDIO_MODE_MONO = 0x3;
3194
3195static const unsigned short PLM_AUDIO_SAMPLE_RATE[] = {
3196 44100, 48000, 32000, 0, // MPEG-1
3197 22050, 24000, 16000, 0 // MPEG-2
3198};
3199
3200static const short PLM_AUDIO_BIT_RATE[] = {
3201 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, // MPEG-1
3202 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 // MPEG-2
3203};
3204
3205static const int PLM_AUDIO_SCALEFACTOR_BASE[] = {0x02000000, 0x01965FEA, 0x01428A30};
3206
3207static const float PLM_AUDIO_SYNTHESIS_WINDOW[] = {
3208 0.0, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -1.0, -1.0, -1.0, -1.0,
3209 -1.5, -1.5, -2.0, -2.0, -2.5, -2.5, -3.0, -3.5, -3.5, -4.0, -4.5,
3210 -5.0, -5.5, -6.5, -7.0, -8.0, -8.5, -9.5, -10.5, -12.0, -13.0, -14.5,
3211 -15.5, -17.5, -19.0, -20.5, -22.5, -24.5, -26.5, -29.0, -31.5, -34.0, -36.5,
3212 -39.5, -42.5, -45.5, -48.5, -52.0, -55.5, -58.5, -62.5, -66.0, -69.5, -73.5,
3213 -77.0, -80.5, -84.5, -88.0, -91.5, -95.0, -98.0, -101.0, -104.0, 106.5, 109.0,
3214 111.0, 112.5, 113.5, 114.0, 114.0, 113.5, 112.0, 110.5, 107.5, 104.0, 100.0,
3215 94.5, 88.5, 81.5, 73.0, 63.5, 53.0, 41.5, 28.5, 14.5, -1.0, -18.0,
3216 -36.0, -55.5, -76.5, -98.5, -122.0, -147.0, -173.5, -200.5, -229.5, -259.5, -290.5,
3217 -322.5, -355.5, -389.5, -424.0, -459.5, -495.5, -532.0, -568.5, -605.0, -641.5, -678.0,
3218 -714.0, -749.0, -783.5, -817.0, -849.0, -879.5, -908.5, -935.0, -959.5, -981.0, -1000.5,
3219 -1016.0, -1028.5, -1037.5, -1042.5, -1043.5, -1040.0, -1031.5, 1018.5, 1000.0, 976.0, 946.5,
3220 911.0, 869.5, 822.0, 767.5, 707.0, 640.0, 565.5, 485.0, 397.0, 302.5, 201.0,
3221 92.5, -22.5, -144.0, -272.5, -407.0, -547.5, -694.0, -846.0, -1003.0, -1165.0, -1331.5,
3222 -1502.0, -1675.5, -1852.5, -2031.5, -2212.5, -2394.0, -2576.5, -2758.5, -2939.5, -3118.5, -3294.5,
3223 -3467.5, -3635.5, -3798.5, -3955.0, -4104.5, -4245.5, -4377.5, -4499.0, -4609.5, -4708.0, -4792.5,
3224 -4863.5, -4919.0, -4958.0, -4979.5, -4983.0, -4967.5, -4931.5, -4875.0, -4796.0, -4694.5, -4569.5,
3225 -4420.0, -4246.0, -4046.0, -3820.0, -3567.0, 3287.0, 2979.5, 2644.0, 2280.5, 1888.0, 1467.5,
3226 1018.5, 541.0, 35.0, -499.0, -1061.0, -1650.0, -2266.5, -2909.0, -3577.0, -4270.0, -4987.5,
3227 -5727.5, -6490.0, -7274.0, -8077.5, -8899.5, -9739.0, -10594.5, -11464.5, -12347.0, -13241.0, -14144.5,
3228 -15056.0, -15973.5, -16895.5, -17820.0, -18744.5, -19668.0, -20588.0, -21503.0, -22410.5, -23308.5, -24195.0,
3229 -25068.5, -25926.5, -26767.0, -27589.0, -28389.0, -29166.5, -29919.0, -30644.5, -31342.0, -32009.5, -32645.0,
3230 -33247.0, -33814.5, -34346.0, -34839.5, -35295.0, -35710.0, -36084.5, -36417.5, -36707.5, -36954.0, -37156.5,
3231 -37315.0, -37428.0, -37496.0, 37519.0, 37496.0, 37428.0, 37315.0, 37156.5, 36954.0, 36707.5, 36417.5,
3232 36084.5, 35710.0, 35295.0, 34839.5, 34346.0, 33814.5, 33247.0, 32645.0, 32009.5, 31342.0, 30644.5,
3233 29919.0, 29166.5, 28389.0, 27589.0, 26767.0, 25926.5, 25068.5, 24195.0, 23308.5, 22410.5, 21503.0,
3234 20588.0, 19668.0, 18744.5, 17820.0, 16895.5, 15973.5, 15056.0, 14144.5, 13241.0, 12347.0, 11464.5,
3235 10594.5, 9739.0, 8899.5, 8077.5, 7274.0, 6490.0, 5727.5, 4987.5, 4270.0, 3577.0, 2909.0,
3236 2266.5, 1650.0, 1061.0, 499.0, -35.0, -541.0, -1018.5, -1467.5, -1888.0, -2280.5, -2644.0,
3237 -2979.5, 3287.0, 3567.0, 3820.0, 4046.0, 4246.0, 4420.0, 4569.5, 4694.5, 4796.0, 4875.0,
3238 4931.5, 4967.5, 4983.0, 4979.5, 4958.0, 4919.0, 4863.5, 4792.5, 4708.0, 4609.5, 4499.0,
3239 4377.5, 4245.5, 4104.5, 3955.0, 3798.5, 3635.5, 3467.5, 3294.5, 3118.5, 2939.5, 2758.5,
3240 2576.5, 2394.0, 2212.5, 2031.5, 1852.5, 1675.5, 1502.0, 1331.5, 1165.0, 1003.0, 846.0,
3241 694.0, 547.5, 407.0, 272.5, 144.0, 22.5, -92.5, -201.0, -302.5, -397.0, -485.0,
3242 -565.5, -640.0, -707.0, -767.5, -822.0, -869.5, -911.0, -946.5, -976.0, -1000.0, 1018.5,
3243 1031.5, 1040.0, 1043.5, 1042.5, 1037.5, 1028.5, 1016.0, 1000.5, 981.0, 959.5, 935.0,
3244 908.5, 879.5, 849.0, 817.0, 783.5, 749.0, 714.0, 678.0, 641.5, 605.0, 568.5,
3245 532.0, 495.5, 459.5, 424.0, 389.5, 355.5, 322.5, 290.5, 259.5, 229.5, 200.5,
3246 173.5, 147.0, 122.0, 98.5, 76.5, 55.5, 36.0, 18.0, 1.0, -14.5, -28.5,
3247 -41.5, -53.0, -63.5, -73.0, -81.5, -88.5, -94.5, -100.0, -104.0, -107.5, -110.5,
3248 -112.0, -113.5, -114.0, -114.0, -113.5, -112.5, -111.0, -109.0, 106.5, 104.0, 101.0,
3249 98.0, 95.0, 91.5, 88.0, 84.5, 80.5, 77.0, 73.5, 69.5, 66.0, 62.5,
3250 58.5, 55.5, 52.0, 48.5, 45.5, 42.5, 39.5, 36.5, 34.0, 31.5, 29.0,
3251 26.5, 24.5, 22.5, 20.5, 19.0, 17.5, 15.5, 14.5, 13.0, 12.0, 10.5,
3252 9.5, 8.5, 8.0, 7.0, 6.5, 5.5, 5.0, 4.5, 4.0, 3.5, 3.5,
3253 3.0, 2.5, 2.5, 2.0, 2.0, 1.5, 1.5, 1.0, 1.0, 1.0, 1.0,
3254 0.5, 0.5, 0.5, 0.5, 0.5, 0.5};
3255
3256// Quantizer lookup, step 1: bitrate classes
3257static const uint8_t PLM_AUDIO_QUANT_LUT_STEP_1[2][16] = {
3258 // 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384 <- bitrate
3259 {0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2}, // mono
3260 // 16, 24, 28, 32, 40, 48, 56, 64, 80, 96,112,128,160,192 <- bitrate / chan
3261 {0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2} // stereo
3262};
3263
3264// Quantizer lookup, step 2: bitrate class, sample rate -> B2 table idx, sblimit
3265#define PLM_AUDIO_QUANT_TAB_A (27 | 64) // Table 3-B.2a: high-rate, sblimit = 27
3266#define PLM_AUDIO_QUANT_TAB_B (30 | 64) // Table 3-B.2b: high-rate, sblimit = 30
3267#define PLM_AUDIO_QUANT_TAB_C 8 // Table 3-B.2c: low-rate, sblimit = 8
3268#define PLM_AUDIO_QUANT_TAB_D 12 // Table 3-B.2d: low-rate, sblimit = 12
3269
3270static const uint8_t QUANT_LUT_STEP_2[3][3] = {
3271 // 44.1 kHz, 48 kHz, 32 kHz
3272 {PLM_AUDIO_QUANT_TAB_C, PLM_AUDIO_QUANT_TAB_C, PLM_AUDIO_QUANT_TAB_D}, // 32 - 48 kbit/sec/ch
3273 {PLM_AUDIO_QUANT_TAB_A, PLM_AUDIO_QUANT_TAB_A, PLM_AUDIO_QUANT_TAB_A}, // 56 - 80 kbit/sec/ch
3274 {PLM_AUDIO_QUANT_TAB_B, PLM_AUDIO_QUANT_TAB_A, PLM_AUDIO_QUANT_TAB_B} // 96+ kbit/sec/ch
3275};
3276
3277// Quantizer lookup, step 3: B2 table, subband -> nbal, row index
3278// (upper 4 bits: nbal, lower 4 bits: row index)
3279static const uint8_t PLM_AUDIO_QUANT_LUT_STEP_3[3][32] = {
3280 // Low-rate table (3-B.2c and 3-B.2d)
3281 {0x44, 0x44, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34},
3282 // High-rate table (3-B.2a and 3-B.2b)
3283 {0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x31, 0x31, 0x31, 0x31,
3284 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20},
3285 // MPEG-2 LSR table (B.2 in ISO 13818-3)
3286 {0x45, 0x45, 0x45, 0x45, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x24, 0x24, 0x24, 0x24,
3287 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24}};
3288
3289// Quantizer lookup, step 4: table row, allocation[] value -> quant table index
3290static const uint8_t PLM_AUDIO_QUANT_LUT_STEP_4[6][16] = {{0, 1, 2, 17},
3291 {0, 1, 2, 3, 4, 5, 6, 17},
3292 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17},
3293 {0, 1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17},
3294 {0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17},
3295 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
3296
3297typedef struct plm_quantizer_spec_t {
3298 unsigned short levels;
3299 unsigned char group;
3300 unsigned char bits;
3301} plm_quantizer_spec_t;
3302
3303static const plm_quantizer_spec_t PLM_AUDIO_QUANT_TAB[] = {
3304 {3, 1, 5}, // 1
3305 {5, 1, 7}, // 2
3306 {7, 0, 3}, // 3
3307 {9, 1, 10}, // 4
3308 {15, 0, 4}, // 5
3309 {31, 0, 5}, // 6
3310 {63, 0, 6}, // 7
3311 {127, 0, 7}, // 8
3312 {255, 0, 8}, // 9
3313 {511, 0, 9}, // 10
3314 {1023, 0, 10}, // 11
3315 {2047, 0, 11}, // 12
3316 {4095, 0, 12}, // 13
3317 {8191, 0, 13}, // 14
3318 {16383, 0, 14}, // 15
3319 {32767, 0, 15}, // 16
3320 {65535, 0, 16} // 17
3321};
3322
3323struct plm_audio_t {
3324 double time;
3325 int samples_decoded;
3326 int samplerate_index;
3327 int bitrate_index;
3328 int version;
3329 int layer;
3330 int mode;
3331 int bound;
3332 int v_pos;
3333 int next_frame_data_size;
3334 int has_header;
3335
3336 plm_buffer_t *buffer;
3337 int destroy_buffer_when_done;
3338
3339 const plm_quantizer_spec_t *allocation[2][32];
3340 uint8_t scale_factor_info[2][32];
3341 int scale_factor[2][32][3];
3342 int sample[2][32][3];
3343
3344 plm_samples_t samples;
3345 float D[1024];
3346 float V[2][1024];
3347 float U[32];
3348};
3349
3350int plm_audio_find_frame_sync(plm_audio_t *self);
3351int plm_audio_decode_header(plm_audio_t *self);
3352void plm_audio_decode_frame(plm_audio_t *self);
3353const plm_quantizer_spec_t *plm_audio_read_allocation(plm_audio_t *self, int sb, int tab3);
3354void plm_audio_read_samples(plm_audio_t *self, int ch, int sb, int part);
3355void plm_audio_idct36(int s[32][3], int ss, float *d, int dp);
3356
3357plm_audio_t *plm_audio_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done) {
3358 plm_audio_t *self = (plm_audio_t *)PLM_MALLOC(sizeof(plm_audio_t));
3359 memset(self, 0, sizeof(plm_audio_t));
3360
3361 self->samples.count = PLM_AUDIO_SAMPLES_PER_FRAME;
3362 self->buffer = buffer;
3363 self->destroy_buffer_when_done = destroy_when_done;
3364 self->samplerate_index = 3; // Indicates 0
3365
3366 memcpy(self->D, PLM_AUDIO_SYNTHESIS_WINDOW, 512 * sizeof(float));
3367 memcpy(self->D + 512, PLM_AUDIO_SYNTHESIS_WINDOW, 512 * sizeof(float));
3368
3369 // Attempt to decode first header
3370 self->next_frame_data_size = plm_audio_decode_header(self);
3371
3372 return self;
3373}
3374
3375void plm_audio_destroy(plm_audio_t *self) {
3376 if (self->destroy_buffer_when_done) {
3377 plm_buffer_destroy(self->buffer);
3378 }
3379 PLM_FREE(self);
3380}
3381
3382int plm_audio_has_header(plm_audio_t *self) {
3383 if (self->has_header) {
3384 return TRUE;
3385 }
3386
3387 self->next_frame_data_size = plm_audio_decode_header(self);
3388 return self->has_header;
3389}
3390
3391int plm_audio_get_samplerate(plm_audio_t *self) {
3392 return plm_audio_has_header(self) ? PLM_AUDIO_SAMPLE_RATE[self->samplerate_index] : 0;
3393}
3394
3395double plm_audio_get_time(plm_audio_t *self) { return self->time; }
3396
3397void plm_audio_set_time(plm_audio_t *self, double time) {
3398 self->samples_decoded = time * (double)PLM_AUDIO_SAMPLE_RATE[self->samplerate_index];
3399 self->time = time;
3400}
3401
3402void plm_audio_rewind(plm_audio_t *self) {
3403 plm_buffer_rewind(self->buffer);
3404 self->time = 0;
3405 self->samples_decoded = 0;
3406 self->next_frame_data_size = 0;
3407}
3408
3409int plm_audio_has_ended(plm_audio_t *self) { return plm_buffer_has_ended(self->buffer); }
3410
3411plm_samples_t *plm_audio_decode(plm_audio_t *self) {
3412 // Do we have at least enough information to decode the frame header?
3413 if (!self->next_frame_data_size) {
3414 if (!plm_buffer_has(self->buffer, 48)) {
3415 return NULL;
3416 }
3417 self->next_frame_data_size = plm_audio_decode_header(self);
3418 }
3419
3420 if (self->next_frame_data_size == 0 || !plm_buffer_has(self->buffer, self->next_frame_data_size << 3)) {
3421 return NULL;
3422 }
3423
3424 plm_audio_decode_frame(self);
3425 self->next_frame_data_size = 0;
3426
3427 self->samples.time = self->time;
3428
3429 self->samples_decoded += PLM_AUDIO_SAMPLES_PER_FRAME;
3430 self->time = (double)self->samples_decoded / (double)PLM_AUDIO_SAMPLE_RATE[self->samplerate_index];
3431
3432 return &self->samples;
3433}
3434
3435int plm_audio_find_frame_sync(plm_audio_t *self) {
3436 size_t i;
3437 for (i = self->buffer->bit_index >> 3; i < self->buffer->length - 1; i++) {
3438 if (self->buffer->bytes[i] == 0xFF && (self->buffer->bytes[i + 1] & 0xFE) == 0xFC) {
3439 self->buffer->bit_index = ((i + 1) << 3) + 3;
3440 return TRUE;
3441 }
3442 }
3443 self->buffer->bit_index = (i + 1) << 3;
3444 return FALSE;
3445}
3446
3447int plm_audio_decode_header(plm_audio_t *self) {
3448 if (!plm_buffer_has(self->buffer, 48)) {
3449 return 0;
3450 }
3451
3452 plm_buffer_skip_bytes(self->buffer, 0x00);
3453 int sync = plm_buffer_read(self->buffer, 11);
3454
3455 // Attempt to resync if no syncword was found. This sucks balls. The MP2
3456 // stream contains a syncword just before every frame (11 bits set to 1).
3457 // However, this syncword is not guaranteed to not occur elsewhere in the
3458 // stream. So, if we have to resync, we also have to check if the header
3459 // (samplerate, bitrate) differs from the one we had before. This all
3460 // may still lead to garbage data being decoded :/
3461
3462 if (sync != PLM_AUDIO_FRAME_SYNC && !plm_audio_find_frame_sync(self)) {
3463 return 0;
3464 }
3465
3466 self->version = plm_buffer_read(self->buffer, 2);
3467 self->layer = plm_buffer_read(self->buffer, 2);
3468 int hasCRC = !plm_buffer_read(self->buffer, 1);
3469
3470 if (self->version != PLM_AUDIO_MPEG_1 || self->layer != PLM_AUDIO_LAYER_II) {
3471 return 0;
3472 }
3473
3474 int bitrate_index = plm_buffer_read(self->buffer, 4) - 1;
3475 if (bitrate_index > 13) {
3476 return 0;
3477 }
3478
3479 int samplerate_index = plm_buffer_read(self->buffer, 2);
3480 if (samplerate_index == 3) {
3481 return 0;
3482 }
3483
3484 int padding = plm_buffer_read(self->buffer, 1);
3485 plm_buffer_skip(self->buffer, 1); // f_private
3486 int mode = plm_buffer_read(self->buffer, 2);
3487
3488 // If we already have a header, make sure the samplerate, bitrate and mode
3489 // are still the same, otherwise we might have missed sync.
3490 if (self->has_header &&
3491 (self->bitrate_index != bitrate_index || self->samplerate_index != samplerate_index || self->mode != mode)) {
3492 return 0;
3493 }
3494
3495 self->bitrate_index = bitrate_index;
3496 self->samplerate_index = samplerate_index;
3497 self->mode = mode;
3498 self->has_header = TRUE;
3499
3500 // Parse the mode_extension, set up the stereo bound
3501 if (mode == PLM_AUDIO_MODE_JOINT_STEREO) {
3502 self->bound = (plm_buffer_read(self->buffer, 2) + 1) << 2;
3503 } else {
3504 plm_buffer_skip(self->buffer, 2);
3505 self->bound = (mode == PLM_AUDIO_MODE_MONO) ? 0 : 32;
3506 }
3507
3508 // Discard the last 4 bits of the header and the CRC value, if present
3509 plm_buffer_skip(self->buffer, 4); // copyright(1), original(1), emphasis(2)
3510 if (hasCRC) {
3511 plm_buffer_skip(self->buffer, 16);
3512 }
3513
3514 // Compute frame size, check if we have enough data to decode the whole
3515 // frame.
3516 int bitrate = PLM_AUDIO_BIT_RATE[self->bitrate_index];
3517 int samplerate = PLM_AUDIO_SAMPLE_RATE[self->samplerate_index];
3518 int frame_size = (144000 * bitrate / samplerate) + padding;
3519 return frame_size - (hasCRC ? 6 : 4);
3520}
3521
3522void plm_audio_decode_frame(plm_audio_t *self) {
3523 // Prepare the quantizer table lookups
3524 int tab3 = 0;
3525 int sblimit = 0;
3526
3527 int tab1 = (self->mode == PLM_AUDIO_MODE_MONO) ? 0 : 1;
3528 int tab2 = PLM_AUDIO_QUANT_LUT_STEP_1[tab1][self->bitrate_index];
3529 tab3 = QUANT_LUT_STEP_2[tab2][self->samplerate_index];
3530 sblimit = tab3 & 63;
3531 tab3 >>= 6;
3532
3533 if (self->bound > sblimit) {
3534 self->bound = sblimit;
3535 }
3536
3537 // Read the allocation information
3538 for (int sb = 0; sb < self->bound; sb++) {
3539 self->allocation[0][sb] = plm_audio_read_allocation(self, sb, tab3);
3540 self->allocation[1][sb] = plm_audio_read_allocation(self, sb, tab3);
3541 }
3542
3543 for (int sb = self->bound; sb < sblimit; sb++) {
3544 self->allocation[0][sb] = self->allocation[1][sb] = plm_audio_read_allocation(self, sb, tab3);
3545 }
3546
3547 // Read scale factor selector information
3548 int channels = (self->mode == PLM_AUDIO_MODE_MONO) ? 1 : 2;
3549 for (int sb = 0; sb < sblimit; sb++) {
3550 for (int ch = 0; ch < channels; ch++) {
3551 if (self->allocation[ch][sb]) {
3552 self->scale_factor_info[ch][sb] = plm_buffer_read(self->buffer, 2);
3553 }
3554 }
3555 if (self->mode == PLM_AUDIO_MODE_MONO) {
3556 self->scale_factor_info[1][sb] = self->scale_factor_info[0][sb];
3557 }
3558 }
3559
3560 // Read scale factors
3561 for (int sb = 0; sb < sblimit; sb++) {
3562 for (int ch = 0; ch < channels; ch++) {
3563 if (self->allocation[ch][sb]) {
3564 int *sf = self->scale_factor[ch][sb];
3565 switch (self->scale_factor_info[ch][sb]) {
3566 case 0:
3567 sf[0] = plm_buffer_read(self->buffer, 6);
3568 sf[1] = plm_buffer_read(self->buffer, 6);
3569 sf[2] = plm_buffer_read(self->buffer, 6);
3570 break;
3571 case 1:
3572 sf[0] = sf[1] = plm_buffer_read(self->buffer, 6);
3573 sf[2] = plm_buffer_read(self->buffer, 6);
3574 break;
3575 case 2:
3576 sf[0] = sf[1] = sf[2] = plm_buffer_read(self->buffer, 6);
3577 break;
3578 case 3:
3579 sf[0] = plm_buffer_read(self->buffer, 6);
3580 sf[1] = sf[2] = plm_buffer_read(self->buffer, 6);
3581 break;
3582 }
3583 }
3584 }
3585 if (self->mode == PLM_AUDIO_MODE_MONO) {
3586 self->scale_factor[1][sb][0] = self->scale_factor[0][sb][0];
3587 self->scale_factor[1][sb][1] = self->scale_factor[0][sb][1];
3588 self->scale_factor[1][sb][2] = self->scale_factor[0][sb][2];
3589 }
3590 }
3591
3592 // Coefficient input and reconstruction
3593 int out_pos = 0;
3594 for (int part = 0; part < 3; part++) {
3595 for (int granule = 0; granule < 4; granule++) {
3596
3597 // Read the samples
3598 for (int sb = 0; sb < self->bound; sb++) {
3599 plm_audio_read_samples(self, 0, sb, part);
3600 plm_audio_read_samples(self, 1, sb, part);
3601 }
3602 for (int sb = self->bound; sb < sblimit; sb++) {
3603 plm_audio_read_samples(self, 0, sb, part);
3604 self->sample[1][sb][0] = self->sample[0][sb][0];
3605 self->sample[1][sb][1] = self->sample[0][sb][1];
3606 self->sample[1][sb][2] = self->sample[0][sb][2];
3607 }
3608 for (int sb = sblimit; sb < 32; sb++) {
3609 self->sample[0][sb][0] = 0;
3610 self->sample[0][sb][1] = 0;
3611 self->sample[0][sb][2] = 0;
3612 self->sample[1][sb][0] = 0;
3613 self->sample[1][sb][1] = 0;
3614 self->sample[1][sb][2] = 0;
3615 }
3616
3617 // Synthesis loop
3618 for (int p = 0; p < 3; p++) {
3619 // Shifting step
3620 self->v_pos = (self->v_pos - 64) & 1023;
3621
3622 for (int ch = 0; ch < 2; ch++) {
3623 plm_audio_idct36(self->sample[ch], p, self->V[ch], self->v_pos);
3624
3625 // Build U, windowing, calculate output
3626 memset(self->U, 0, sizeof(self->U));
3627
3628 int d_index = 512 - (self->v_pos >> 1);
3629 int v_index = (self->v_pos % 128) >> 1;
3630 while (v_index < 1024) {
3631 for (int i = 0; i < 32; ++i) {
3632 self->U[i] += self->D[d_index++] * self->V[ch][v_index++];
3633 }
3634
3635 v_index += 128 - 32;
3636 d_index += 64 - 32;
3637 }
3638
3639 d_index -= (512 - 32);
3640 v_index = (128 - 32 + 1024) - v_index;
3641 while (v_index < 1024) {
3642 for (int i = 0; i < 32; ++i) {
3643 self->U[i] += self->D[d_index++] * self->V[ch][v_index++];
3644 }
3645
3646 v_index += 128 - 32;
3647 d_index += 64 - 32;
3648 }
3649
3650// Output samples
3651#ifdef PLM_AUDIO_SEPARATE_CHANNELS
3652 float *out_channel = ch == 0 ? self->samples.left : self->samples.right;
3653 for (int j = 0; j < 32; j++) {
3654 out_channel[out_pos + j] = self->U[j] / 2147418112.0f;
3655 }
3656#else
3657 for (int j = 0; j < 32; j++) {
3658 self->samples.interleaved[((out_pos + j) << 1) + ch] = self->U[j] / 2147418112.0f;
3659 }
3660#endif
3661 } // End of synthesis channel loop
3662 out_pos += 32;
3663 } // End of synthesis sub-block loop
3664
3665 } // Decoding of the granule finished
3666 }
3667
3668 plm_buffer_align(self->buffer);
3669}
3670
3671const plm_quantizer_spec_t *plm_audio_read_allocation(plm_audio_t *self, int sb, int tab3) {
3672 int tab4 = PLM_AUDIO_QUANT_LUT_STEP_3[tab3][sb];
3673 int qtab = PLM_AUDIO_QUANT_LUT_STEP_4[tab4 & 15][plm_buffer_read(self->buffer, tab4 >> 4)];
3674 return qtab ? (&PLM_AUDIO_QUANT_TAB[qtab - 1]) : 0;
3675}
3676
3677void plm_audio_read_samples(plm_audio_t *self, int ch, int sb, int part) {
3678 const plm_quantizer_spec_t *q = self->allocation[ch][sb];
3679 int sf = self->scale_factor[ch][sb][part];
3680 int *sample = self->sample[ch][sb];
3681 int val = 0;
3682
3683 if (!q) {
3684 // No bits allocated for this subband
3685 sample[0] = sample[1] = sample[2] = 0;
3686 return;
3687 }
3688
3689 // Resolve scalefactor
3690 if (sf == 63) {
3691 sf = 0;
3692 } else {
3693 int shift = (sf / 3) | 0;
3694 sf = (PLM_AUDIO_SCALEFACTOR_BASE[sf % 3] + ((1 << shift) >> 1)) >> shift;
3695 }
3696
3697 // Decode samples
3698 int adj = q->levels;
3699 if (q->group) {
3700 // Decode grouped samples
3701 val = plm_buffer_read(self->buffer, q->bits);
3702 sample[0] = val % adj;
3703 val /= adj;
3704 sample[1] = val % adj;
3705 sample[2] = val / adj;
3706 } else {
3707 // Decode direct samples
3708 sample[0] = plm_buffer_read(self->buffer, q->bits);
3709 sample[1] = plm_buffer_read(self->buffer, q->bits);
3710 sample[2] = plm_buffer_read(self->buffer, q->bits);
3711 }
3712
3713 // Postmultiply samples
3714 int scale = 65536 / (adj + 1);
3715 adj = ((adj + 1) >> 1) - 1;
3716
3717 val = (adj - sample[0]) * scale;
3718 sample[0] = (val * (sf >> 12) + ((val * (sf & 4095) + 2048) >> 12)) >> 12;
3719
3720 val = (adj - sample[1]) * scale;
3721 sample[1] = (val * (sf >> 12) + ((val * (sf & 4095) + 2048) >> 12)) >> 12;
3722
3723 val = (adj - sample[2]) * scale;
3724 sample[2] = (val * (sf >> 12) + ((val * (sf & 4095) + 2048) >> 12)) >> 12;
3725}
3726
3727void plm_audio_idct36(int s[32][3], int ss, float *d, int dp) {
3728 float t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22,
3729 t23, t24, t25, t26, t27, t28, t29, t30, t31, t32, t33;
3730
3731 t01 = (float)(s[0][ss] + s[31][ss]);
3732 t02 = (float)(s[0][ss] - s[31][ss]) * 0.500602998235f;
3733 t03 = (float)(s[1][ss] + s[30][ss]);
3734 t04 = (float)(s[1][ss] - s[30][ss]) * 0.505470959898f;
3735 t05 = (float)(s[2][ss] + s[29][ss]);
3736 t06 = (float)(s[2][ss] - s[29][ss]) * 0.515447309923f;
3737 t07 = (float)(s[3][ss] + s[28][ss]);
3738 t08 = (float)(s[3][ss] - s[28][ss]) * 0.53104259109f;
3739 t09 = (float)(s[4][ss] + s[27][ss]);
3740 t10 = (float)(s[4][ss] - s[27][ss]) * 0.553103896034f;
3741 t11 = (float)(s[5][ss] + s[26][ss]);
3742 t12 = (float)(s[5][ss] - s[26][ss]) * 0.582934968206f;
3743 t13 = (float)(s[6][ss] + s[25][ss]);
3744 t14 = (float)(s[6][ss] - s[25][ss]) * 0.622504123036f;
3745 t15 = (float)(s[7][ss] + s[24][ss]);
3746 t16 = (float)(s[7][ss] - s[24][ss]) * 0.674808341455f;
3747 t17 = (float)(s[8][ss] + s[23][ss]);
3748 t18 = (float)(s[8][ss] - s[23][ss]) * 0.744536271002f;
3749 t19 = (float)(s[9][ss] + s[22][ss]);
3750 t20 = (float)(s[9][ss] - s[22][ss]) * 0.839349645416f;
3751 t21 = (float)(s[10][ss] + s[21][ss]);
3752 t22 = (float)(s[10][ss] - s[21][ss]) * 0.972568237862f;
3753 t23 = (float)(s[11][ss] + s[20][ss]);
3754 t24 = (float)(s[11][ss] - s[20][ss]) * 1.16943993343f;
3755 t25 = (float)(s[12][ss] + s[19][ss]);
3756 t26 = (float)(s[12][ss] - s[19][ss]) * 1.48416461631f;
3757 t27 = (float)(s[13][ss] + s[18][ss]);
3758 t28 = (float)(s[13][ss] - s[18][ss]) * 2.05778100995f;
3759 t29 = (float)(s[14][ss] + s[17][ss]);
3760 t30 = (float)(s[14][ss] - s[17][ss]) * 3.40760841847f;
3761 t31 = (float)(s[15][ss] + s[16][ss]);
3762 t32 = (float)(s[15][ss] - s[16][ss]) * 10.1900081235f;
3763
3764 t33 = t01 + t31;
3765 t31 = (t01 - t31) * 0.502419286188f;
3766 t01 = t03 + t29;
3767 t29 = (t03 - t29) * 0.52249861494f;
3768 t03 = t05 + t27;
3769 t27 = (t05 - t27) * 0.566944034816f;
3770 t05 = t07 + t25;
3771 t25 = (t07 - t25) * 0.64682178336f;
3772 t07 = t09 + t23;
3773 t23 = (t09 - t23) * 0.788154623451f;
3774 t09 = t11 + t21;
3775 t21 = (t11 - t21) * 1.06067768599f;
3776 t11 = t13 + t19;
3777 t19 = (t13 - t19) * 1.72244709824f;
3778 t13 = t15 + t17;
3779 t17 = (t15 - t17) * 5.10114861869f;
3780 t15 = t33 + t13;
3781 t13 = (t33 - t13) * 0.509795579104f;
3782 t33 = t01 + t11;
3783 t01 = (t01 - t11) * 0.601344886935f;
3784 t11 = t03 + t09;
3785 t09 = (t03 - t09) * 0.899976223136f;
3786 t03 = t05 + t07;
3787 t07 = (t05 - t07) * 2.56291544774f;
3788 t05 = t15 + t03;
3789 t15 = (t15 - t03) * 0.541196100146f;
3790 t03 = t33 + t11;
3791 t11 = (t33 - t11) * 1.30656296488f;
3792 t33 = t05 + t03;
3793 t05 = (t05 - t03) * 0.707106781187f;
3794 t03 = t15 + t11;
3795 t15 = (t15 - t11) * 0.707106781187f;
3796 t03 += t15;
3797 t11 = t13 + t07;
3798 t13 = (t13 - t07) * 0.541196100146f;
3799 t07 = t01 + t09;
3800 t09 = (t01 - t09) * 1.30656296488f;
3801 t01 = t11 + t07;
3802 t07 = (t11 - t07) * 0.707106781187f;
3803 t11 = t13 + t09;
3804 t13 = (t13 - t09) * 0.707106781187f;
3805 t11 += t13;
3806 t01 += t11;
3807 t11 += t07;
3808 t07 += t13;
3809 t09 = t31 + t17;
3810 t31 = (t31 - t17) * 0.509795579104f;
3811 t17 = t29 + t19;
3812 t29 = (t29 - t19) * 0.601344886935f;
3813 t19 = t27 + t21;
3814 t21 = (t27 - t21) * 0.899976223136f;
3815 t27 = t25 + t23;
3816 t23 = (t25 - t23) * 2.56291544774f;
3817 t25 = t09 + t27;
3818 t09 = (t09 - t27) * 0.541196100146f;
3819 t27 = t17 + t19;
3820 t19 = (t17 - t19) * 1.30656296488f;
3821 t17 = t25 + t27;
3822 t27 = (t25 - t27) * 0.707106781187f;
3823 t25 = t09 + t19;
3824 t19 = (t09 - t19) * 0.707106781187f;
3825 t25 += t19;
3826 t09 = t31 + t23;
3827 t31 = (t31 - t23) * 0.541196100146f;
3828 t23 = t29 + t21;
3829 t21 = (t29 - t21) * 1.30656296488f;
3830 t29 = t09 + t23;
3831 t23 = (t09 - t23) * 0.707106781187f;
3832 t09 = t31 + t21;
3833 t31 = (t31 - t21) * 0.707106781187f;
3834 t09 += t31;
3835 t29 += t09;
3836 t09 += t23;
3837 t23 += t31;
3838 t17 += t29;
3839 t29 += t25;
3840 t25 += t09;
3841 t09 += t27;
3842 t27 += t23;
3843 t23 += t19;
3844 t19 += t31;
3845 t21 = t02 + t32;
3846 t02 = (t02 - t32) * 0.502419286188f;
3847 t32 = t04 + t30;
3848 t04 = (t04 - t30) * 0.52249861494f;
3849 t30 = t06 + t28;
3850 t28 = (t06 - t28) * 0.566944034816f;
3851 t06 = t08 + t26;
3852 t08 = (t08 - t26) * 0.64682178336f;
3853 t26 = t10 + t24;
3854 t10 = (t10 - t24) * 0.788154623451f;
3855 t24 = t12 + t22;
3856 t22 = (t12 - t22) * 1.06067768599f;
3857 t12 = t14 + t20;
3858 t20 = (t14 - t20) * 1.72244709824f;
3859 t14 = t16 + t18;
3860 t16 = (t16 - t18) * 5.10114861869f;
3861 t18 = t21 + t14;
3862 t14 = (t21 - t14) * 0.509795579104f;
3863 t21 = t32 + t12;
3864 t32 = (t32 - t12) * 0.601344886935f;
3865 t12 = t30 + t24;
3866 t24 = (t30 - t24) * 0.899976223136f;
3867 t30 = t06 + t26;
3868 t26 = (t06 - t26) * 2.56291544774f;
3869 t06 = t18 + t30;
3870 t18 = (t18 - t30) * 0.541196100146f;
3871 t30 = t21 + t12;
3872 t12 = (t21 - t12) * 1.30656296488f;
3873 t21 = t06 + t30;
3874 t30 = (t06 - t30) * 0.707106781187f;
3875 t06 = t18 + t12;
3876 t12 = (t18 - t12) * 0.707106781187f;
3877 t06 += t12;
3878 t18 = t14 + t26;
3879 t26 = (t14 - t26) * 0.541196100146f;
3880 t14 = t32 + t24;
3881 t24 = (t32 - t24) * 1.30656296488f;
3882 t32 = t18 + t14;
3883 t14 = (t18 - t14) * 0.707106781187f;
3884 t18 = t26 + t24;
3885 t24 = (t26 - t24) * 0.707106781187f;
3886 t18 += t24;
3887 t32 += t18;
3888 t18 += t14;
3889 t26 = t14 + t24;
3890 t14 = t02 + t16;
3891 t02 = (t02 - t16) * 0.509795579104f;
3892 t16 = t04 + t20;
3893 t04 = (t04 - t20) * 0.601344886935f;
3894 t20 = t28 + t22;
3895 t22 = (t28 - t22) * 0.899976223136f;
3896 t28 = t08 + t10;
3897 t10 = (t08 - t10) * 2.56291544774f;
3898 t08 = t14 + t28;
3899 t14 = (t14 - t28) * 0.541196100146f;
3900 t28 = t16 + t20;
3901 t20 = (t16 - t20) * 1.30656296488f;
3902 t16 = t08 + t28;
3903 t28 = (t08 - t28) * 0.707106781187f;
3904 t08 = t14 + t20;
3905 t20 = (t14 - t20) * 0.707106781187f;
3906 t08 += t20;
3907 t14 = t02 + t10;
3908 t02 = (t02 - t10) * 0.541196100146f;
3909 t10 = t04 + t22;
3910 t22 = (t04 - t22) * 1.30656296488f;
3911 t04 = t14 + t10;
3912 t10 = (t14 - t10) * 0.707106781187f;
3913 t14 = t02 + t22;
3914 t02 = (t02 - t22) * 0.707106781187f;
3915 t14 += t02;
3916 t04 += t14;
3917 t14 += t10;
3918 t10 += t02;
3919 t16 += t04;
3920 t04 += t08;
3921 t08 += t14;
3922 t14 += t28;
3923 t28 += t10;
3924 t10 += t20;
3925 t20 += t02;
3926 t21 += t16;
3927 t16 += t32;
3928 t32 += t04;
3929 t04 += t06;
3930 t06 += t08;
3931 t08 += t18;
3932 t18 += t14;
3933 t14 += t30;
3934 t30 += t28;
3935 t28 += t26;
3936 t26 += t10;
3937 t10 += t12;
3938 t12 += t20;
3939 t20 += t24;
3940 t24 += t02;
3941
3942 d[dp + 48] = -t33;
3943 d[dp + 49] = d[dp + 47] = -t21;
3944 d[dp + 50] = d[dp + 46] = -t17;
3945 d[dp + 51] = d[dp + 45] = -t16;
3946 d[dp + 52] = d[dp + 44] = -t01;
3947 d[dp + 53] = d[dp + 43] = -t32;
3948 d[dp + 54] = d[dp + 42] = -t29;
3949 d[dp + 55] = d[dp + 41] = -t04;
3950 d[dp + 56] = d[dp + 40] = -t03;
3951 d[dp + 57] = d[dp + 39] = -t06;
3952 d[dp + 58] = d[dp + 38] = -t25;
3953 d[dp + 59] = d[dp + 37] = -t08;
3954 d[dp + 60] = d[dp + 36] = -t11;
3955 d[dp + 61] = d[dp + 35] = -t18;
3956 d[dp + 62] = d[dp + 34] = -t09;
3957 d[dp + 63] = d[dp + 33] = -t14;
3958 d[dp + 32] = -t05;
3959 d[dp + 0] = t05;
3960 d[dp + 31] = -t30;
3961 d[dp + 1] = t30;
3962 d[dp + 30] = -t27;
3963 d[dp + 2] = t27;
3964 d[dp + 29] = -t28;
3965 d[dp + 3] = t28;
3966 d[dp + 28] = -t07;
3967 d[dp + 4] = t07;
3968 d[dp + 27] = -t26;
3969 d[dp + 5] = t26;
3970 d[dp + 26] = -t23;
3971 d[dp + 6] = t23;
3972 d[dp + 25] = -t10;
3973 d[dp + 7] = t10;
3974 d[dp + 24] = -t15;
3975 d[dp + 8] = t15;
3976 d[dp + 23] = -t12;
3977 d[dp + 9] = t12;
3978 d[dp + 22] = -t19;
3979 d[dp + 10] = t19;
3980 d[dp + 21] = -t20;
3981 d[dp + 11] = t20;
3982 d[dp + 20] = -t13;
3983 d[dp + 12] = t13;
3984 d[dp + 19] = -t24;
3985 d[dp + 13] = t24;
3986 d[dp + 18] = -t31;
3987 d[dp + 14] = t31;
3988 d[dp + 17] = -t02;
3989 d[dp + 15] = t02;
3990 d[dp + 16] = 0.0;
3991}
3992
3993#endif // PL_MPEG_IMPLEMENTATION