Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/flvdec.c')
-rw-r--r--libavformat/flvdec.c76
1 files changed, 66 insertions, 10 deletions
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 34945299b6..765eee5893 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -37,6 +37,10 @@
typedef struct {
int wrong_dts; ///< wrong dts due to negative cts
+ uint8_t *new_extradata[FLV_STREAM_TYPE_NB];
+ int new_extradata_size[FLV_STREAM_TYPE_NB];
+ int last_sample_rate;
+ int last_channels;
} FLVContext;
static int flv_probe(AVProbeData *p)
@@ -50,8 +54,7 @@ static int flv_probe(AVProbeData *p)
return 0;
}
-static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, int flv_codecid) {
- AVCodecContext *acodec = astream->codec;
+static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecContext *acodec, int flv_codecid) {
switch(flv_codecid) {
//no distinction between S16 and S8 PCM codec flags
case FLV_CODECID_PCM:
@@ -411,6 +414,15 @@ static int flv_read_header(AVFormatContext *s,
return 0;
}
+static int flv_read_close(AVFormatContext *s)
+{
+ int i;
+ FLVContext *flv = s->priv_data;
+ for(i=0; i<FLV_STREAM_TYPE_NB; i++)
+ av_freep(&flv->new_extradata[i]);
+ return 0;
+}
+
static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
{
av_free(st->codec->extradata);
@@ -422,6 +434,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;
@@ -429,6 +453,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
int stream_type=-1;
int64_t next, pos;
int64_t dts, pts = AV_NOPTS_VALUE;
+ int sample_rate, channels;
AVStream *st = NULL;
for(;;avio_skip(s->pb, 4)){ /* pkt size is repeated at end. skip it */
@@ -518,13 +543,24 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
}
if(stream_type == FLV_STREAM_TYPE_AUDIO){
+ int bits_per_coded_sample;
+ channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
+ sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);
+ bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
if(!st->codec->channels || !st->codec->sample_rate || !st->codec->bits_per_coded_sample) {
- st->codec->channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
- st->codec->sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3);
- st->codec->bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
+ st->codec->channels = channels;
+ st->codec->sample_rate = sample_rate;
+ st->codec->bits_per_coded_sample = bits_per_coded_sample;
}
if(!st->codec->codec_id){
- flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK);
+ flv_set_audio_codec(s, st, st->codec, flags & FLV_AUDIO_CODECID_MASK);
+ flv->last_sample_rate = st->codec->sample_rate;
+ flv->last_channels = st->codec->channels;
+ } else {
+ AVCodecContext ctx;
+ ctx.sample_rate = sample_rate;
+ flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK);
+ sample_rate = ctx.sample_rate;
}
} else if(stream_type == FLV_STREAM_TYPE_VIDEO) {
size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK);
@@ -545,8 +581,13 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
if (flv->wrong_dts)
dts = AV_NOPTS_VALUE;
}
-
- if (type == 0 && !st->codec->extradata) {
+ if (type == 0 && (!st->codec->extradata || st->codec->codec_id != CODEC_ID_H264)) {
+ if (st->codec->extradata) {
+ if ((ret = flv_queue_extradata(flv, s->pb, stream_type, 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) {
@@ -583,8 +624,22 @@ 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(st->codec->codec_id == CODEC_ID_NELLYMOSER)
- av_packet_new_side_data(pkt, 'F', 1)[0]= flags;
+ if (flv->new_extradata[stream_type]) {
+ uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
+ flv->new_extradata_size[stream_type]);
+ if (side) {
+ memcpy(side, flv->new_extradata[stream_type],
+ flv->new_extradata_size[stream_type]);
+ av_freep(&flv->new_extradata[stream_type]);
+ flv->new_extradata_size[stream_type] = 0;
+ }
+ }
+ if (stream_type == FLV_STREAM_TYPE_AUDIO && (sample_rate != flv->last_sample_rate ||
+ channels != flv->last_channels)) {
+ flv->last_sample_rate = sample_rate;
+ flv->last_channels = channels;
+ ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0);
+ }
if ( stream_type == FLV_STREAM_TYPE_AUDIO ||
((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) ||
@@ -640,6 +695,7 @@ AVInputFormat ff_flv_demuxer = {
#if 0
.read_seek2 = flv_read_seek2,
#endif
+ .read_close = flv_read_close,
.extensions = "flv",
.value = CODEC_ID_FLV1,
};