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:
parent
195c123cc8
commit
251f320f7d
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user