[FFmpeg-devel] [PATCH] start FLAC decoding mid-stream
Justin Ruggles
justin.ruggles
Mon Dec 8 23:48:29 CET 2008
Michael Niedermayer wrote:
> On Sun, Dec 07, 2008 at 05:32:02PM -0500, Justin Ruggles wrote:
>> Justin Ruggles wrote:
>>> Hi,
>>>
>>> As mentioned in another thread, our FLAC decoder cannot start decoding
>>> mid-stream without having the STREAMINFO. The FLAC format allows for
>>> doing this as long as each frame header supplies all the necessary info.
>>>
>>> Here is a patch to allow decoding starting anywhere in a FLAC stream.
>>>
>>> Thanks,
>>> Justin
>> Here is a slightly better version which only allocates buffers once if
>> starting mid-stream.
>>
>> -Justin
>>
>
>> Index: libavcodec/flac.c
>> ===================================================================
>> --- libavcodec/flac.c (revision 16030)
>> +++ libavcodec/flac.c (working copy)
>> @@ -102,6 +102,11 @@ static av_cold int flac_decode_init(AVCodecContext
>> FLACContext *s = avctx->priv_data;
>> s->avctx = avctx;
>>
>> + s->min_blocksize = 16;
>> + s->max_blocksize = 32768;
>
>> + s->samplerate = -1;
>> + s->channels = -1;
>> + s->bps = -1;
>
> is 0 for these not good enough?
yeah, 0 is good enough. I'll change it.
>
>> if (avctx->extradata_size > 4) {
>> /* initialize based on the demuxer-supplied streamdata header */
>> if (avctx->extradata_size == FLAC_STREAMINFO_SIZE) {
>> @@ -131,7 +136,7 @@ static void allocate_buffers(FLACContext *s){
>>
>> assert(s->max_blocksize);
>>
>> - if(s->max_framesize == 0 && s->max_blocksize){
>> + if(s->max_blocksize){
>> s->max_framesize= (s->channels * s->bps * s->max_blocksize + 7)/ 8; //FIXME header overhead
>> }
>>
>
> why?
After explaining it to myself several times (it's been a long day), it's
clear to me that the crux of the issue is that currently the STREAMINFO
can contain a 0 for max_framesize, indicating unknown, so that section
is a fallback. We need to ALWAYS use the fallback when we don't have a
STREAMINFO, but max_framesize is set to non-zero before we get to this
point. So now I think a better way to solve it might be to set
max_framesize to zero when allocate_buffers == 1 in decode_frame().
That would effectively mimic a 0 value in the STREAMINFO.
>
>> @@ -495,12 +500,25 @@ static int decode_frame(FLACContext *s, int alloc_
>> {
>> int blocksize_code, sample_rate_code, sample_size_code, assignment, i, crc8;
>> int decorrelation, bps, blocksize, samplerate;
>> + int allocate_buffers = 0;
>>
>> blocksize_code = get_bits(&s->gb, 4);
>>
>> sample_rate_code = get_bits(&s->gb, 4);
>>
>> assignment = get_bits(&s->gb, 4); /* channel assignment */
>> + if (s->channels < 0)
>> + {
>> + if (assignment < 8)
>> + {
>> + s->channels = assignment + 1;
>> + }
>> + else
>> + {
>> + s->channels = 2;
>> + }
>> + allocate_buffers = 1;
>> + }
>
> why is this under channels < 0 ?
The idea was that the number of channels shouldn't change mid-stream.
That is not currently supported, but I could fabricate a test stream and
try to support it. Then again, I don't know if ffmpeg/ffplay would
support it either. It is handled in AC3 by silently changing the mixing
within the decoder, but I don't think that would be desirable for a
lossless codec.
>
> [...]
>> @@ -570,6 +605,12 @@ static int decode_frame(FLACContext *s, int alloc_
>> av_log(s->avctx, AV_LOG_ERROR, "illegal sample rate code %d\n", sample_rate_code);
>> return -1;
>> }
>> + if (s->samplerate < 0) {
>> + s->avctx->sample_rate = samplerate;
>
>> + } else if (samplerate != s->avctx->sample_rate) {
>> + av_log(s->avctx, AV_LOG_ERROR, "cannot change sample rate mid-stream\n");
>> + return -1;
>> + }
>>
>> skip_bits(&s->gb, 8);
>> crc8 = av_crc(av_crc_get_table(AV_CRC_8_ATM), 0,
>
> what is the problem with it changing?
Same deal as channels (and bps for that matter). I can try to add
support for it. It would be interesting to see how libFLAC handles it,
so I'll give it a shot.
>
>> @@ -584,6 +625,9 @@ static int decode_frame(FLACContext *s, int alloc_
>> s->bps = bps;
>> s->decorrelation= decorrelation;
>>
>> + if (allocate_buffers)
>> + return 1;
>> +
>> // dump_headers(s->avctx, (FLACStreaminfo *)s);
>>
>> /* subframes */
>> @@ -658,11 +702,17 @@ static int flac_decode_frame(AVCodecContext *avctx
>> goto end; // we may not have enough bits left to decode a frame, so try next time
>> }
>> skip_bits(&s->gb, 16);
>> - if (decode_frame(s, alloc_data_size) < 0){
>> - av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
>> + tmp = decode_frame(s, alloc_data_size);
>> + if (tmp) {
>> s->bitstream_size=0;
>> s->bitstream_index=0;
>
>> + if (tmp < 0) {
>> + av_log(s->avctx, AV_LOG_ERROR, "decode_frame() failed\n");
>
> one of these 2 lines is not correctly indented
Yeah, one of the lines is just moved, not modified, so I didn't change
the indentation... either way it would be fixed in a follow-up commit.
Plus that whole section is currently incorrectly indented, so I was
going to correct that too.
Thanks,
Justin
More information about the ffmpeg-devel
mailing list