FMV: Fixed timing of frame events and parameters

- Decoupled SEQ event from GOP event.
  Now behaves like real VMPEG hardware
- Fixes Lost Ride gameplay after vehicle charge intro
- Fixes timing accuracy of temp ref and time code
  Measurable with mv_status()
This commit is contained in:
Andre Zeps
2026-02-20 08:42:34 +01:00
parent 176e9b6403
commit 594bae844e
16 changed files with 1825 additions and 1670 deletions

11
CDi.sdc
View File

@@ -34,4 +34,13 @@ set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|latched_window_offs
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|latched_window_offset_x*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|frameplayer:frameplayer|window_x_clkddr*}
# protection not required because of context
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|fmv_slow_motion*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|slow_motion_clkddr*}
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|fmv_slow_motion*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|slow_motion_clkddr*}
# protected by latency between latch_frame_for_display and latch_frame_for_display_clk_mpeg
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_timecode*}
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_tempref*}
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_width*}
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|display_height*}
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|first_intra_frame_of_gop_clk30}
set_false_path -from {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|yuv_frame_adr_fifo:readyframes|*} -to {emu:emu|cditop:cditop|vmpeg:vmpeg_inst|mpeg_video:video|first_intra_frame_of_seq_clk30}

2
CDi.sv
View File

@@ -230,7 +230,7 @@ module emu (
"P2F1,ROM,Replace Boot ROM;",
"P2O[2],Disable Audio Att.,No,Yes;",
"P2O[3],UART Fake Space,No,Yes;",
"P2O[7:6],Force Video Plane,Original,A,B;",
"P2O[7:6],Force Video Plane,Original,A,B,DVC;",
"P2O[12],SERVO Audio CD,No,Yes;",
"P2O[17],Disable VCD pixel clock,No,Yes;",
"P2O[18],Activate VCD filter,Yes,No;",

View File

@@ -188,6 +188,8 @@ by emulation errors but are also present on the real machine.
* During the intro of "The Ultimate Noah's Ark", the Mike Wilks artwork has repeated pixels on the bottom and right edge.
* This looks wrong but real hardware does that too.
* There is also a weirdly wrong column of pixels during the title page on the left inside the black frame
* "Marlboro Follow Your Dreams" is not booting and hangs on a cyan screen
* You are probably using NTSC mode. Being made by a German publisher, this title was probably only tested on European models. It behaves like this on real hardware as well
## Simulation

View File

@@ -223,3 +223,13 @@ cat log | grep 'FMV INT\|XFER\|DVC Read e04062\|PIC2\|GOP' > log2
1 Overclock input device No, Yes
(it is rather long. It could be shorter?)
Lost Ride:
Syscall @ ded9b2 8e I$SetStt 00000006 00000122 00000002 00000900 0000ab00 00001999 0000bca0 00000000 00df9340 00000000 00d0d1d8 00dffd90 00d0bc98 00d0bb26 00d08000 00dfd428 SetStt MA_Loop
Syscall @ deda82 8e I$SetStt 00000006 00000124 00000002 00000000 0000bd00 00000000 0000ffff 00000000 00df9340 00040e20 00d0d1d8 00dffd90 00d03b56 00d0bb26 00d08000 00dfd428 SetStt MA_Play
FMA Write Stream Number 1804 0000
FMA IER 180e 013d
FMA CMD 1800 0002
Syscall @ ded8c6 8e I$SetStt 00000006 00000120 00000002 00800080 f5020000 00000000 0000bca0 00000000 00df9340 00000000 00d0d1d8 00dffd90 00d0bc98 00d0bb26 00d08000 00dfd428 SetStt MA_Cntrl

View File

@@ -385,7 +385,8 @@ module cditop (
.ddrif
);
assign vidout = mcd212_vsd ? fmv_video_out : mcd212_video_out;
wire force_dvc_video = debug_force_video_plane == 2'b11;
assign vidout = (mcd212_vsd || force_dvc_video) ? fmv_video_out : mcd212_video_out;
`ifndef DISABLE_MAIN_CPU
wire reset68k;

View File

@@ -1353,7 +1353,7 @@ module mcd212 (
vsd = backdrop_pixel && image_coding_method_register.ev;
`ifdef VERILATOR
// vsd = 1;
//vsd = 1;
`endif
end

View File

@@ -55,6 +55,11 @@ module mpeg_audio (
event_frame_decoded <= 0;
event_underflow <= 0;
if (fifo_full) begin
$display("AUDIO FIFO FULL");
$finish();
end
if (reset || reset_input_fifo) begin
mpeg_stream_fifo_write_adr <= 0;
mpeg_stream_bit_index <= 0;

File diff suppressed because it is too large Load Diff

View File

@@ -37,12 +37,16 @@ module mpeg_video (
output event_buffer_underflow,
output bit event_picture_starts_display,
output event_last_picture_starts_display,
output bit event_first_intra_frame_starts_display,
output bit event_first_intra_frame_gop_starts_display,
output bit event_first_intra_frame_seq_starts_display,
output [4:0] pictures_in_fifo,
output bit [10:0] decoder_width,
output bit [ 8:0] decoder_height,
output bit [ 7:0] decoder_tempref,
output bit [10:0] display_width,
output bit [ 8:0] display_height,
output bit [ 7:0] display_tempref,
output bit [31:0] display_timecode,
output bit [15:0] decoder_frameperiod_90khz,
output bit [ 7:0] decoder_frameperiod_rawhdr
);
@@ -594,6 +598,12 @@ module mpeg_video (
if (dmem_cmd_payload_address_1[15:0] == 16'h3038) begin
just_decoded.tempref <= dmem_cmd_payload_data_1[7:0];
end
if (dmem_cmd_payload_address_1[15:0] == 16'h3044) begin
just_decoded.timecode <= dmem_cmd_payload_data_1;
end
if (dmem_cmd_payload_address_1[15:0] == 16'h3048) begin
just_decoded.first_intra_frame_of_seq <= dmem_cmd_payload_data_1[0];
end
if (dmem_cmd_payload_address_1[15:0] == 16'h2010) begin
has_sequence_header <= dmem_cmd_payload_data_1[0];
@@ -638,8 +648,8 @@ module mpeg_video (
bit [23:0] playback_frame_cnt;
bit latch_frame_until_vblank = 0;
bit first_intra_frame_of_gop_in_prep;
bit first_intra_frame_of_gop_clk30;
bit first_intra_frame_of_seq_clk30;
bit vblank_q1;
bit vblank_q2;
@@ -658,14 +668,18 @@ module mpeg_video (
.flag_out_clk_b(just_decoded_commit_clk30)
);
always_ff @(posedge clk30) begin
vblank_q1 <= vblank;
vblank_q2 <= vblank_q1;
if (latch_frame_for_display) begin
decoder_width <= for_display.width;
decoder_height <= for_display.height;
decoder_tempref <= for_display.tempref;
display_width <= for_display.width;
display_height <= for_display.height;
display_tempref <= for_display.tempref;
display_timecode <= for_display.timecode;
first_intra_frame_of_gop_clk30 <= for_display.first_intra_frame_of_gop;
first_intra_frame_of_seq_clk30 <= for_display.first_intra_frame_of_seq;
end
if (just_decoded_commit_clk30) begin
@@ -680,16 +694,18 @@ module mpeg_video (
decoder_width <= 0;
decoder_height <= 0;
frame_period <= 0;
decoder_tempref <= 0;
display_tempref <= 0;
display_timecode <= 0;
decoder_frameperiod_90khz <= 0;
decoder_frameperiod_rawhdr <= 0;
end
for_display_valid <= for_display_valid_clk_mpeg;
first_intra_frame_of_gop_clk30 <= for_display.first_intra_frame_of_gop;
event_picture_starts_display <= 0;
event_first_intra_frame_starts_display <= 0;
event_first_intra_frame_gop_starts_display <= 0;
event_first_intra_frame_seq_starts_display <= 0;
event_last_picture_starts_display <= 0;
latch_frame_for_display <= 0;
@@ -697,7 +713,8 @@ module mpeg_video (
if (latch_frame_until_vblank && !vblank && vblank_q1 && vblank_q2) begin
latch_frame_until_vblank <= 0;
event_picture_starts_display <= 1;
event_first_intra_frame_starts_display <= first_intra_frame_of_gop_in_prep;
event_first_intra_frame_gop_starts_display <= first_intra_frame_of_gop_clk30;
event_first_intra_frame_seq_starts_display <= first_intra_frame_of_seq_clk30;
event_last_picture_starts_display <= !for_display_valid;
end
@@ -708,16 +725,14 @@ module mpeg_video (
if (playback_frame_cnt >= frame_period - 1) playback_frame_cnt <= 0;
if (playback_frame_cnt == 0 && for_display_valid) begin
latch_frame_for_display <= 1;
latch_frame_for_display <= 1;
latch_frame_until_vblank <= 1;
first_intra_frame_of_gop_in_prep <= first_intra_frame_of_gop_clk30;
end
end
if (single_step) begin
latch_frame_until_vblank <= 1;
latch_frame_for_display <= 1;
first_intra_frame_of_gop_in_prep <= first_intra_frame_of_gop_clk30;
latch_frame_for_display <= 1;
end
end

View File

@@ -6,9 +6,11 @@ typedef struct {
bit [28:0] u_adr;
bit [28:0] v_adr;
bit first_intra_frame_of_gop;
bit first_intra_frame_of_seq;
bit [10:0] width;
bit [8:0] height;
bit [7:0] tempref;
bit [31:0] timecode;
} planar_yuv_s;
typedef struct packed {
@@ -18,7 +20,6 @@ typedef struct packed {
bit [7:0] factor_l2l;
} linear_volume_s;
function [31:0] ones_mask(bit [4:0] n);
begin
ones_mask = (32'h1 << n) - 1; // n ones at LSB

View File

@@ -106,10 +106,8 @@ module vmpeg (
wire fmv_event_picture_starts_display;
wire fmv_event_last_picture_starts_display;
wire fmv_event_first_intra_frame_starts_display;
wire fmv_event_sequence_header = fmv_event_first_intra_frame_starts_display;
wire fmv_event_group_of_pictures = fmv_event_first_intra_frame_starts_display;
wire fmv_event_picture = fmv_event_picture_starts_display;
wire fmv_event_first_intra_frame_seq_starts_display;
wire fmv_event_first_intra_frame_gop_starts_display;
// TIMECD @ 00E04058
// example 0x07800280 -> 10:00:30.0
// mv_info() would have MD_TimeCd=0x0a001e00
@@ -117,7 +115,7 @@ module vmpeg (
// [27:22] 6 Bit Seconds. Not BCD
// [5:0] 6 Bit Minutes. Not BCD
// [10:6] 5 Bits Hours. Not BCD
wire [31:0] fmv_timecode;
wire [31:0] fmv_display_timecode;
bit fmv_playback_active;
bit fmv_single_step;
wire fmv_event_sequence_end;
@@ -163,11 +161,15 @@ module vmpeg (
.event_buffer_underflow(fmv_event_buffer_underflow),
.event_picture_starts_display(fmv_event_picture_starts_display),
.event_last_picture_starts_display(fmv_event_last_picture_starts_display),
.event_first_intra_frame_starts_display(fmv_event_first_intra_frame_starts_display),
.event_first_intra_frame_gop_starts_display(fmv_event_first_intra_frame_gop_starts_display),
.event_first_intra_frame_seq_starts_display(fmv_event_first_intra_frame_seq_starts_display),
.pictures_in_fifo(fmv_pictures_in_fifo),
.decoder_width(fmv_decoder_width),
.decoder_height(fmv_decoder_height),
.decoder_tempref(fmv_decoder_tempref),
.display_width(fmv_display_width),
.display_height(fmv_display_height),
.display_tempref(fmv_display_tempref),
.display_timecode(fmv_display_timecode),
.decoder_frameperiod_90khz(fmv_decoder_frameperiod_90khz),
.decoder_frameperiod_rawhdr(fmv_decoder_frameperiod_rawhdr)
);
@@ -182,18 +184,6 @@ module vmpeg (
end
end
mpeg_video_start_code_decoder startcode (
.clk,
.reset,
.mpeg_data(mpeg_data),
.data_valid(fmv_data_valid && fmv_packet_body),
.event_sequence_header(),
.event_group_of_pictures(),
.event_picture(),
.tmpref(),
.timecode(fmv_timecode)
);
wire signed [32:0] fma_system_clock_reference_start_time;
wire fma_system_clock_reference_start_time_valid;
wire signed [32:0] fmv_system_clock_reference_start_time;
@@ -398,7 +388,10 @@ module vmpeg (
wire [10:0] fmv_decoder_width;
wire [ 8:0] fmv_decoder_height;
wire [ 7:0] fmv_decoder_tempref;
wire [10:0] fmv_display_width;
wire [ 8:0] fmv_display_height;
wire [ 7:0] fmv_display_tempref;
wire [15:0] fmv_decoder_frameperiod_90khz;
wire [ 7:0] fmv_decoder_frameperiod_rawhdr;
@@ -468,14 +461,16 @@ module vmpeg (
15'h2001: dout = image_width; // 00E04002 ?? Written then Read
15'h2002: dout = image_height; // 00E04004 ?? Written then Read
15'h2003: dout = image_rt; // 00E04006 ??
15'h2004: dout = fmv_timecode[31:16]; // 00E04008 Temporal time code High. During scan
15'h2005: dout = fmv_timecode[15:0]; // 00E0400C Temporal time code Low. During scan
15'h2029: dout = {5'b0, fmv_decoder_width}; // e04052 Picture Width ?? Only read
15'h202a: dout = {7'b0, fmv_decoder_height}; // e04054 Picture Height ?? Only read
15'h2004:
dout = fmv_display_timecode[15:0]; // 00E04008 Temporal time code High. During scan
15'h2005:
dout = fmv_display_timecode[31:16]; // 00E0400C Temporal time code Low. During scan
15'h2029: dout = {5'b0, fmv_display_width}; // e04052 Picture Width ?? Only read
15'h202a: dout = {7'b0, fmv_display_height}; // e04054 Picture Height ?? Only read
15'h202b: dout = {8'b0, fmv_decoder_frameperiod_rawhdr}; // e04056 Pic Rt ??
15'h202c: dout = fmv_timecode[31:16]; // 00E04058 Time Code High ??
15'h202d: dout = fmv_timecode[15:0]; // 00E0405A Time Code Low ??
15'h202e: dout = {6'b0, fmv_decoder_tempref, 2'b0}; // 00E0405C TMP REF?? SYS_VSR?
15'h202c: dout = fmv_display_timecode[15:0]; // 00E04058 Time Code High ??
15'h202d: dout = fmv_display_timecode[31:16]; // 00E0405A Time Code Low ??
15'h202e: dout = {6'b0, fmv_display_tempref, 2'b0}; // 00E0405C TMP REF?? SYS_VSR?
15'h202f: dout = fmv_fifo_full ? 0 : 16'h2000; // 00E0405E ? SYS_STS
15'h2030: dout = fmv_interrupt_enable_register; // 0E04060
15'h2031: dout = fmv_interrupt_status_register; // 0E04062
@@ -613,12 +608,13 @@ module vmpeg (
end
end
if (fmv_event_sequence_header) begin
if (fmv_event_first_intra_frame_seq_starts_display) begin
fmv_interrupt_status_register.seq <= 1;
$display("Cause FMV Seq Event");
end
if (fmv_event_group_of_pictures) fmv_interrupt_status_register.gop <= 1;
if (fmv_event_picture) begin
if (fmv_event_first_intra_frame_gop_starts_display)
fmv_interrupt_status_register.gop <= 1;
if (fmv_event_picture_starts_display) begin
fmv_interrupt_status_register.pic <= 1;
image_width <= {5'b0, fmv_decoder_width};

View File

@@ -21,7 +21,7 @@
#define SCC68070
#define SLAVE
// #define TRACE
#define TRACE
// #define SIMULATE_RC5
#define PL_MPEG_IMPLEMENTATION
@@ -888,7 +888,7 @@ class CDi {
dut.rootp->emu__DOT__cditop__DOT__fdrvs1_static = cpu_a[2];
}
#if 0
#if 1
executing_dvc_rom_instructions = m_pc >= 0xe40000 && m_pc < 0xe7ffff;
#endif
if (print_instructions || executing_dvc_rom_instructions) {
@@ -929,6 +929,7 @@ class CDi {
// PAL
// space_ace_pal();
// braindead13_pal();
lost_ride_pal();
}
#endif
@@ -971,9 +972,9 @@ class CDi {
}
// Simulate Audio
if (dut.rootp->emu__DOT__cditop__DOT__sample_tick44) {
int16_t sample_l = dut.rootp->emu__DOT__cditop__DOT__vmpeg_inst__DOT__audio__DOT__fifo_out_left;
int16_t sample_r = dut.rootp->emu__DOT__cditop__DOT__vmpeg_inst__DOT__audio__DOT__fifo_out_right;
if (dut.rootp->emu__DOT__cditop__DOT__cdic_inst__DOT__sample_tick) {
int16_t sample_l = dut.rootp->emu__DOT__cditop__DOT__cdic_inst__DOT__adpcm__DOT__fifo_out_left;
int16_t sample_r = dut.rootp->emu__DOT__cditop__DOT__cdic_inst__DOT__adpcm__DOT__fifo_out_right;
fwrite(&sample_l, 2, 1, f_audio_left);
fwrite(&sample_r, 2, 1, f_audio_right);
}
@@ -1306,7 +1307,7 @@ int main(int argc, char **argv) {
switch (machineindex) {
case 0:
f_cd_bin = fopen("images/braindead13.bin", "rb");
f_cd_bin = fopen("images/nonis2.bin", "rb");
break;
case 1:
f_cd_bin = fopen("images/braindead13.bin", "rb");

View File

@@ -10,7 +10,7 @@ main:
move.w #$0000,$303FFE ; Data buffer
move.w #$0002,$E03000 ; FMA CMD - On
move.w #$0006,$E03008 ; FMA Stream
move.w #$0000,$E03008 ; FMA Stream
move.w #$2000,$E040C0 ; FMV SYSCMD - Decoder off
nop
@@ -56,7 +56,7 @@ main:
move.w #$0100,$303C06 ; File Register
move.l #$ffffffff,$303C08 ; Channel Register
move.w #$0000,$303C0C ; Audio Channel Register
move.l #$01133900,$303C02 ; Timer Register
move.l #$00323400,$303C02 ; Timer Register
move.w #$C000,$303FFE ; Start the Read by setting bit 15 of the data buffer
move.l #0,$0E0407C ;FMV_DECOFF
@@ -68,7 +68,7 @@ main:
; But I feel lazy and use the number of pics instead
waitforpics:
jsr WaitForSectorAndUse
cmp.w #4,$00E040A4 ; Compare 5 against pictures in FIFO
cmp.w #2,$00E040A4 ; Compare 5 against pictures in FIFO
bmi waitforpics
move.w #$0008,$E040C0 ; FMV SYSCMD - Play

View File

@@ -30,6 +30,9 @@ struct frame_display_fifo
uint32_t temporal_ref; // @0x10003038 Write only
uint32_t slow_motion; // @0x1000303c Read only
uint32_t commit_frame; // @0x10003040 Write only
uint32_t timecode; // @0x10003044 Write only
uint32_t first_intra_frame_of_seq; // @0x10003048 Write only
};
struct io_fifo_control *const fifo_ctrl = (struct io_fifo_control *)0x10002000;

View File

@@ -30,6 +30,7 @@ void print_str(const char *p);
void stop_verilator();
// #define SOFT_CONVOLVE
int seq_hdr_latched;
#define PL_MPEG_IMPLEMENTATION
#define PLM_NO_STDIO
@@ -109,10 +110,14 @@ static void push_frame(plm_frame_t *frame)
{
first_intra_frame_of_gop_occured = true;
frame_display_fifo->first_intra_frame_of_gop = 1;
frame_display_fifo->first_intra_frame_of_seq = seq_hdr_latched;
seq_hdr_latched = false;
}
else
{
frame_display_fifo->first_intra_frame_of_gop = 0;
frame_display_fifo->first_intra_frame_of_seq = 0;
}
frame_display_fifo->width = frame->width;
@@ -124,6 +129,7 @@ static void push_frame(plm_frame_t *frame)
frame_display_fifo->frameperiod_90khz = period90khz;
frame_display_fifo->frameperiod_rawhdr = seq_hdr_conf.frameperiod;
frame_display_fifo->temporal_ref = frame->temporal_ref;
frame_display_fifo->timecode = frame->timecode;
if (frame_display_fifo->pictures_in_fifo < 3)
{

View File

@@ -186,6 +186,8 @@ typedef struct plm_video_t plm_video_t;
typedef struct plm_audio_t plm_audio_t;
int seq_hdr_latched;
// Demuxed MPEG PS packet
// The type maps directly to the various MPEG-PES start codes. PTS is the
// presentation time stamp of the packet in seconds. Note that not all packets
@@ -229,6 +231,7 @@ typedef struct {
plm_plane_t cb;
int picture_type;
int temporal_ref;
int timecode;
} plm_frame_t;
@@ -1504,6 +1507,7 @@ static const int PLM_START_SLICE_LAST = 0xAF;
static const int PLM_START_PICTURE = 0x00;
static const int PLM_START_EXTENSION = 0xB5;
static const int PLM_START_USER_DATA = 0xB2;
static const int PLM_START_GROUP_OF_PICTURES = 0xB8;
#define PLM_START_IS_SLICE(c) \
(c >= PLM_START_SLICE_FIRST && c <= PLM_START_SLICE_LAST)
@@ -1985,6 +1989,7 @@ struct plm_video_t {
int start_code;
int picture_type;
int temporal_ref;
int timecode; // from GOP
plm_video_motion_t motion_forward;
plm_video_motion_t motion_backward;
@@ -2022,6 +2027,7 @@ static inline uint8_t plm_clamp(int n) {
return n;
}
int plm_video_decode_group_of_pictures(plm_video_t *self);
int plm_video_decode_sequence_header(plm_video_t *self);
void plm_video_init_frame(plm_video_t *self, plm_frame_t *frame);
void plm_video_decode_picture(plm_video_t *self);
@@ -2155,6 +2161,9 @@ plm_frame_t *plm_video_decode(plm_video_t *self) {
}
plm_video_decode_sequence_header(self);
}
else if (self->start_code == PLM_START_GROUP_OF_PICTURES){
plm_video_decode_group_of_pictures(self);
}
else if (self->start_code == -1) {
// If we reached the end of the file and the previously decoded
// frame was a reference frame, we still have to return it.
@@ -2176,7 +2185,6 @@ plm_frame_t *plm_video_decode(plm_video_t *self) {
} while (!frame);
OUT_DEBUG = 15;
frame->time = self->time;
@@ -2205,6 +2213,24 @@ int plm_video_has_header(plm_video_t *self) {
return TRUE;
}
int plm_video_decode_group_of_pictures(plm_video_t *self) {
if (!plm_dma_buffer_has(self->buffer, 11+2+12)) {
return FALSE;
}
// skip drop frame flag
plm_dma_buffer_skip(self->buffer, 1);
uint32_t hours_minutes = plm_dma_buffer_read(self->buffer, 11);
// skip marker
plm_dma_buffer_skip(self->buffer, 1);
uint32_t seconds_frame = plm_dma_buffer_read(self->buffer, 12);
self->timecode = (hours_minutes<<12) | seconds_frame;
}
int plm_video_decode_sequence_header(plm_video_t *self) {
int max_header_size = 64 + 2 * 64 * 8; // 64 bit header + 2x 64 byte matrix
if (!plm_dma_buffer_has(self->buffer, max_header_size)) {
@@ -2273,6 +2299,8 @@ int plm_video_decode_sequence_header(plm_video_t *self) {
plm_video_init_frame(self, &self->frame_forward);
plm_video_init_frame(self, &self->frame_backward);
}
__asm volatile("": : :"memory");
seq_hdr_latched=1;
return TRUE;
}
@@ -2361,10 +2389,10 @@ void plm_video_decode_picture(plm_video_t *self) {
// Decode all slices
plm_video_init_frame(self, &self->frame_current);
self->frame_current.picture_type = self->picture_type;
self->frame_current.temporal_ref = self->temporal_ref;
self->frame_current.timecode = self->timecode;
while (PLM_START_IS_SLICE(self->start_code)) {
OUT_DEBUG = 7;