1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-21 10:55:51 +02:00

flvdec: Export new AAC/H.264 extradata as side data on the next packet

Compared to just overwriting the old extradata, this has the
advantage of letting the decoder know exactly when the
extradata changed (otherwise it is changed immediately when the
new extradata packet is demuxed, even if there's old queued packets
awaiting to be decoded). This makes it easier for decoders to
actually react to the change, so they won't have to inspect
the extradata for each packet to see if it might have changed.

This works when sequentially playing a file with sample rate
changes, but if seeking past a new extradata packet in the
file, it obviously doesn't work properly. That case doesn't
work in flash player either, so it's probably ok not to handle
it.

Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
Martin Storsjö 2011-12-15 16:29:55 +02:00
parent 195c123cc8
commit 251f320f7d

View File

@ -41,6 +41,8 @@
typedef struct {
int wrong_dts; ///< wrong dts due to negative cts
uint8_t *new_extradata[2];
int new_extradata_size[2];
} FLVContext;
static int flv_probe(AVProbeData *p)
@ -401,6 +403,14 @@ static int flv_read_header(AVFormatContext *s,
return 0;
}
static int flv_read_close(AVFormatContext *s)
{
FLVContext *flv = s->priv_data;
av_freep(&flv->new_extradata[0]);
av_freep(&flv->new_extradata[1]);
return 0;
}
static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
{
av_free(st->codec->extradata);
@ -412,6 +422,18 @@ static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
return 0;
}
static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream,
int size)
{
av_free(flv->new_extradata[stream]);
flv->new_extradata[stream] = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE);
if (!flv->new_extradata[stream])
return AVERROR(ENOMEM);
flv->new_extradata_size[stream] = size;
avio_read(pb, flv->new_extradata[stream], size);
return 0;
}
static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
FLVContext *flv = s->priv_data;
@ -529,6 +551,12 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
dts = AV_NOPTS_VALUE;
}
if (type == 0) {
if (st->codec->extradata) {
if ((ret = flv_queue_extradata(flv, s->pb, is_audio, size)) < 0)
return ret;
ret = AVERROR(EAGAIN);
goto leave;
}
if ((ret = flv_get_extradata(s, st, size)) < 0)
return ret;
if (st->codec->codec_id == CODEC_ID_AAC) {
@ -565,6 +593,16 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt->dts = dts;
pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts;
pkt->stream_index = st->index;
if (flv->new_extradata[is_audio]) {
uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
flv->new_extradata_size[is_audio]);
if (side) {
memcpy(side, flv->new_extradata[is_audio],
flv->new_extradata_size[is_audio]);
av_freep(&flv->new_extradata[is_audio]);
flv->new_extradata_size[is_audio] = 0;
}
}
if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY))
pkt->flags |= AV_PKT_FLAG_KEY;
@ -618,6 +656,7 @@ AVInputFormat ff_flv_demuxer = {
#if 0
.read_seek2 = flv_read_seek2,
#endif
.read_close = flv_read_close,
.extensions = "flv",
.value = CODEC_ID_FLV1,
};