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