phoboslab / pl_mpeg

Single file C library for decoding MPEG1 Video and MP2 Audio

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

System and VideoCD streams

Zero3K opened this issue · comments

Does it support them?

Anyone know if it does or not?

I have just tested with a VCD short AVSEQ02.DAT file, it can play video but failed to decode audio.

Can you please provide the file, so I can have a look?

I have identified the problem, but I'm unsure how to solve it.

This file has a System Header that states num_audio_streams = 0. The library therefor doesn't initialize the audio decoder and just skips over audio packets. I'm not sure if this is a problem with this file specifically, or if this is "by design".

I don't have the reference (Apparently VCD is standardized in the "White Book"; maybe someone can share that?). But as far as I can tell, VCDs MUST contain exactly one audio stream with 44.1kHz and 224kbps bit rate. Why the presence of this stream is omitted in the System Header is a mystery to me.

A simple workaround: force num_audio_streams = 1 right after it's read from the System Header in Line 1784:

plm_buffer_skip(self->buffer, 16); // header_length
plm_buffer_skip(self->buffer, 24); // rate bound
self->num_audio_streams = plm_buffer_read(self->buffer, 6);
self->num_audio_streams = 1; // <- ADD THIS LINE
plm_buffer_skip(self->buffer, 5); // misc flags

A slightly better solution would be to probe deeper into the stream and just look for audio packets. I wouldn't be surprised if this is the "canonical" way to do this, given that MPEG-PS is such a shitty standard :/

If anyone knows more about this: please let me know!

Edit: probing for stream start codes is exactly what ffmpeg does. ffmpeg's encoder also specifically sets audio_bound = 0 for VCD. So this is by design. Not sure I want to go down this road.

I have found same problem but with Loki version of heretic 2 videos, all videos has zero as count of video streams and has video packets.

FFmpeg has played such videos without issues.

I found the DAT file have 2 "00 00 01 BB" headers and the 2nd one have correct audio bound(1). And the DAT file have a RIFF....CDXA header, I think it should have someway to handle it.

Compare with normal MPEG file encoded by FFmpeg, the system audio local flag and system video local flag have different value.

My current thinking is to add another function plm_probe_streams(plm_t *) that reads a few kb into the buffer and looks for video/audio start codes. This would overwrite the num_audio_streams and num_video_streams gathered from the header.

I think this would be the cleanest solution; still allowing streaming applications to start immediately (without probing) but provides more accuracy when loading from files. It would complicate the plm_init_decoders() function a bit, because it's usually called directly within the plm_create_*() functions and would need to be called again from plm_probe_streams() if the result differs from the header.

Thoughts?

plm_probe(plm_t *self, size_t probesize) implemented in above commit. Depending on your video resolution and how frequently audio packets are muxed, probsize might need to be quite large to find all streams. In my tests ~300kb worked fine for 720p video. However, probing is quite fast and plmpeg_player.c uses 5mb, just to be safe.

Note that plm_probe() should only be used with seekable buffers. So if you use a _with_capacity() buffer as underlying data source, you're out of luck.