|
|
|
@ -312,11 +312,17 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static AVStream *create_stream(AVFormatContext *s, int is_audio){ |
|
|
|
|
AVStream *st = av_new_stream(s, is_audio); |
|
|
|
|
static AVStream *create_stream(AVFormatContext *s, int stream_type){ |
|
|
|
|
AVStream *st = av_new_stream(s, stream_type); |
|
|
|
|
if (!st) |
|
|
|
|
return NULL; |
|
|
|
|
st->codec->codec_type = is_audio ? AVMEDIA_TYPE_AUDIO : AVMEDIA_TYPE_VIDEO; |
|
|
|
|
switch(stream_type) { |
|
|
|
|
case FLV_STREAM_TYPE_VIDEO: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; break; |
|
|
|
|
case FLV_STREAM_TYPE_AUDIO: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; break; |
|
|
|
|
case FLV_STREAM_TYPE_DATA: |
|
|
|
|
st->codec->codec_type = AVMEDIA_TYPE_DATA; |
|
|
|
|
st->codec->codec_id = CODEC_ID_NONE; // Going to rely on copy for now
|
|
|
|
|
} |
|
|
|
|
av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ |
|
|
|
|
return st; |
|
|
|
|
} |
|
|
|
@ -340,13 +346,15 @@ static int flv_read_header(AVFormatContext *s, |
|
|
|
|
s->ctx_flags |= AVFMTCTX_NOHEADER; |
|
|
|
|
|
|
|
|
|
if(flags & FLV_HEADER_FLAG_HASVIDEO){ |
|
|
|
|
if(!create_stream(s, 0)) |
|
|
|
|
if(!create_stream(s, FLV_STREAM_TYPE_VIDEO)) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
if(flags & FLV_HEADER_FLAG_HASAUDIO){ |
|
|
|
|
if(!create_stream(s, 1)) |
|
|
|
|
if(!create_stream(s, FLV_STREAM_TYPE_AUDIO)) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
// Flag doesn't indicate whether or not there is script-data present. Must
|
|
|
|
|
// create that stream if it's encountered.
|
|
|
|
|
|
|
|
|
|
offset = avio_rb32(s->pb); |
|
|
|
|
avio_seek(s->pb, offset, SEEK_SET); |
|
|
|
@ -371,7 +379,7 @@ static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size) |
|
|
|
|
static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
{ |
|
|
|
|
FLVContext *flv = s->priv_data; |
|
|
|
|
int ret, i, type, size, flags, is_audio; |
|
|
|
|
int ret, i, type, size, flags, stream_type; |
|
|
|
|
int64_t next, pos; |
|
|
|
|
int64_t dts, pts = AV_NOPTS_VALUE; |
|
|
|
|
AVStream *st = NULL; |
|
|
|
@ -394,20 +402,29 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
next= size + avio_tell(s->pb); |
|
|
|
|
|
|
|
|
|
if (type == FLV_TAG_TYPE_AUDIO) { |
|
|
|
|
is_audio=1; |
|
|
|
|
stream_type=FLV_STREAM_TYPE_AUDIO; |
|
|
|
|
flags = avio_r8(s->pb); |
|
|
|
|
size--; |
|
|
|
|
} else if (type == FLV_TAG_TYPE_VIDEO) { |
|
|
|
|
is_audio=0; |
|
|
|
|
stream_type=FLV_STREAM_TYPE_VIDEO; |
|
|
|
|
flags = avio_r8(s->pb); |
|
|
|
|
size--; |
|
|
|
|
if ((flags & 0xf0) == 0x50) /* video info / command frame */ |
|
|
|
|
goto skip; |
|
|
|
|
} else { |
|
|
|
|
if (type == FLV_TAG_TYPE_META && size > 13+1+4) |
|
|
|
|
} else if (type == FLV_TAG_TYPE_META) { |
|
|
|
|
if (size > 13+1+4 && dts == 0) { |
|
|
|
|
// Header-type metadata stuff
|
|
|
|
|
flv_read_metabody(s, next); |
|
|
|
|
else /* skip packet */ |
|
|
|
|
av_log(s, AV_LOG_DEBUG, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags); |
|
|
|
|
} else if (dts != 0) { |
|
|
|
|
// Script-data
|
|
|
|
|
stream_type=FLV_STREAM_TYPE_VIDEO; |
|
|
|
|
goto skip; |
|
|
|
|
|
|
|
|
|
// TODO: Parse / set stuff, etc.
|
|
|
|
|
} else { |
|
|
|
|
goto skip; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
skip: |
|
|
|
|
avio_seek(s->pb, next, SEEK_SET); |
|
|
|
|
continue; |
|
|
|
@ -420,17 +437,17 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
/* now find stream */ |
|
|
|
|
for(i=0;i<s->nb_streams;i++) { |
|
|
|
|
st = s->streams[i]; |
|
|
|
|
if (st->id == is_audio) |
|
|
|
|
if (st->id == stream_type) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if(i == s->nb_streams){ |
|
|
|
|
av_log(s, AV_LOG_ERROR, "invalid stream\n"); |
|
|
|
|
st= create_stream(s, is_audio); |
|
|
|
|
st= create_stream(s, stream_type); |
|
|
|
|
s->ctx_flags &= ~AVFMTCTX_NOHEADER; |
|
|
|
|
} |
|
|
|
|
av_dlog(s, "%d %X %d \n", is_audio, flags, st->discard); |
|
|
|
|
if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || is_audio)) |
|
|
|
|
||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio)) |
|
|
|
|
av_dlog(s, "%d %X %d \n", stream_type, flags, st->discard); |
|
|
|
|
if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || (stream_type == FLV_STREAM_TYPE_AUDIO))) |
|
|
|
|
||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO))) |
|
|
|
|
|| st->discard >= AVDISCARD_ALL |
|
|
|
|
){ |
|
|
|
|
avio_seek(s->pb, next, SEEK_SET); |
|
|
|
@ -457,7 +474,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
avio_seek(s->pb, pos, SEEK_SET); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(is_audio){ |
|
|
|
|
if(stream_type == FLV_STREAM_TYPE_AUDIO){ |
|
|
|
|
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); |
|
|
|
@ -466,7 +483,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
if(!st->codec->codec_id){ |
|
|
|
|
flv_set_audio_codec(s, st, flags & FLV_AUDIO_CODECID_MASK); |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
} else if(stream_type == FLV_STREAM_TYPE_VIDEO) { |
|
|
|
|
size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -523,7 +540,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts; |
|
|
|
|
pkt->stream_index = st->index; |
|
|
|
|
|
|
|
|
|
if (is_audio || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) |
|
|
|
|
if ((stream_type == FLV_STREAM_TYPE_AUDIO) || ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY)) |
|
|
|
|
pkt->flags |= AV_PKT_FLAG_KEY; |
|
|
|
|
|
|
|
|
|
leave: |
|
|
|
|