You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
shorten: fix end-of-stream decoding.
enable CODEC_CAP_DELAY to flush any remaining frames in the buffer. Stop decoding when the FN_QUIT command is found so that a trailing seek table isn't decoded as a normal frame. decode all channels in the same call to avcodec_decode_audio3() so that decoding will not stop after the first channel of the last frame. Updated FATE reference. More valid audio is now decoded.
This commit is contained in:
@@ -103,6 +103,7 @@ typedef struct ShortenContext {
|
|||||||
int bitindex;
|
int bitindex;
|
||||||
int32_t lpcqoffset;
|
int32_t lpcqoffset;
|
||||||
int got_header;
|
int got_header;
|
||||||
|
int got_quit_command;
|
||||||
} ShortenContext;
|
} ShortenContext;
|
||||||
|
|
||||||
static av_cold int shorten_decode_init(AVCodecContext * avctx)
|
static av_cold int shorten_decode_init(AVCodecContext * avctx)
|
||||||
@@ -425,13 +426,15 @@ static int shorten_decode_frame(AVCodecContext *avctx,
|
|||||||
memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
|
memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
|
||||||
s->bitstream_index=0;
|
s->bitstream_index=0;
|
||||||
}
|
}
|
||||||
|
if (buf)
|
||||||
memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);
|
memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);
|
||||||
buf= &s->bitstream[s->bitstream_index];
|
buf= &s->bitstream[s->bitstream_index];
|
||||||
buf_size += s->bitstream_size;
|
buf_size += s->bitstream_size;
|
||||||
s->bitstream_size= buf_size;
|
s->bitstream_size= buf_size;
|
||||||
|
|
||||||
/* do not decode until buffer has at least max_framesize bytes */
|
/* do not decode until buffer has at least max_framesize bytes or
|
||||||
if(buf_size < s->max_framesize){
|
the end of the file has been reached */
|
||||||
|
if (buf_size < s->max_framesize && avpkt->data) {
|
||||||
*data_size = 0;
|
*data_size = 0;
|
||||||
return input_buf_size;
|
return input_buf_size;
|
||||||
}
|
}
|
||||||
@@ -445,20 +448,31 @@ static int shorten_decode_frame(AVCodecContext *avctx,
|
|||||||
if ((ret = read_header(s)) < 0)
|
if ((ret = read_header(s)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*data_size = 0;
|
*data_size = 0;
|
||||||
|
goto finish_frame;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
/* if quit command was read previously, don't decode anything */
|
||||||
|
if (s->got_quit_command) {
|
||||||
|
*data_size = 0;
|
||||||
|
return avpkt->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->cur_chan = 0;
|
||||||
|
while (s->cur_chan < s->channels) {
|
||||||
int cmd;
|
int cmd;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
if (get_bits_left(&s->gb) < 3+FNSIZE) {
|
||||||
|
*data_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
cmd = get_ur_golomb_shorten(&s->gb, FNSIZE);
|
cmd = get_ur_golomb_shorten(&s->gb, FNSIZE);
|
||||||
|
|
||||||
if (cmd > FN_VERBATIM) {
|
if (cmd > FN_VERBATIM) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd);
|
av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd);
|
||||||
if (s->bitstream_size > 0) {
|
*data_size = 0;
|
||||||
s->bitstream_index++;
|
break;
|
||||||
s->bitstream_size--;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_audio_command[cmd]) {
|
if (!is_audio_command[cmd]) {
|
||||||
@@ -488,9 +502,13 @@ static int shorten_decode_frame(AVCodecContext *avctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FN_QUIT:
|
case FN_QUIT:
|
||||||
|
s->got_quit_command = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) {
|
||||||
*data_size = 0;
|
*data_size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* process audio command */
|
/* process audio command */
|
||||||
int residual_size = 0;
|
int residual_size = 0;
|
||||||
@@ -559,14 +577,14 @@ static int shorten_decode_frame(AVCodecContext *avctx,
|
|||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded);
|
samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded);
|
||||||
s->cur_chan = 0;
|
|
||||||
*data_size = out_size;
|
*data_size = out_size;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->cur_chan < s->channels)
|
||||||
*data_size = 0;
|
*data_size = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
finish_frame:
|
||||||
s->bitindex = get_bits_count(&s->gb) - 8*((get_bits_count(&s->gb))/8);
|
s->bitindex = get_bits_count(&s->gb) - 8*((get_bits_count(&s->gb))/8);
|
||||||
i= (get_bits_count(&s->gb))/8;
|
i= (get_bits_count(&s->gb))/8;
|
||||||
if (i > buf_size) {
|
if (i > buf_size) {
|
||||||
@@ -606,5 +624,6 @@ AVCodec ff_shorten_decoder = {
|
|||||||
.init = shorten_decode_init,
|
.init = shorten_decode_init,
|
||||||
.close = shorten_decode_close,
|
.close = shorten_decode_close,
|
||||||
.decode = shorten_decode_frame,
|
.decode = shorten_decode_frame,
|
||||||
|
.capabilities = CODEC_CAP_DELAY,
|
||||||
.long_name= NULL_IF_CONFIG_SMALL("Shorten"),
|
.long_name= NULL_IF_CONFIG_SMALL("Shorten"),
|
||||||
};
|
};
|
||||||
|
@@ -1 +1 @@
|
|||||||
9949141c405524f37ef1058b1ef4114b
|
da93c50961443b88fce416ae61c8ca8a
|
||||||
|
Reference in New Issue
Block a user