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