support flv demuxer

Signed-off-by: yj <yujie57@huawei.com>
This commit is contained in:
yj 2024-03-14 07:18:08 +00:00
parent c986c5f8b0
commit 5cf89d9e9e
4 changed files with 45 additions and 18 deletions

View File

@ -1146,8 +1146,8 @@ ohos_source_set("ffmpeg_dynamic") {
# "//third_party/ffmpeg/libavformat/flacenc.c",
# "//third_party/ffmpeg/libavformat/flacenc_header.c",
# "//third_party/ffmpeg/libavformat/flic.c",
# "//third_party/ffmpeg/libavformat/flvdec.c",
# "//third_party/ffmpeg/libavformat/flvenc.c",
"//third_party/ffmpeg/libavformat/flvdec.c",
"//third_party/ffmpeg/libavformat/flvenc.c",
"//third_party/ffmpeg/libavformat/format.c",
# "//third_party/ffmpeg/libavformat/framecrcenc.c",

View File

@ -42,7 +42,7 @@
#define FLV_AUDIO_CODECID_MASK 0xf0
#define FLV_VIDEO_CODECID_MASK 0x0f
#define FLV_VIDEO_FRAMETYPE_MASK 0xf0
#define FLV_VIDEO_FRAMETYPE_MASK 0x70
#define AMF_END_OF_OBJECT 0x09
@ -112,6 +112,15 @@ enum {
FLV_CODECID_MPEG4 = 9,
};
enum {
PacketTypeSequenceStart = 0,
PacketTypeCodedFrames = 1,
PacketTypeSequenceEnd = 2,
PacketTypeCodedFramesX = 3,
PacketTypeMetadata = 4,
PacketTypeMPEG2TSSequenceStart = 5,
};
enum {
FLV_FRAME_KEY = 1 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< key frame (for AVC, a seekable frame)
FLV_FRAME_INTER = 2 << FLV_VIDEO_FRAMETYPE_OFFSET, ///< inter frame (for AVC, a non-seekable frame)

View File

@ -300,14 +300,14 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
}
}
static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
static int flv_same_video_codec(AVCodecParameters *vpar, uint32_t flv_codecid)
{
int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
if (!vpar->codec_id && !vpar->codec_tag)
return 1;
switch (flv_codecid) {
case MKBETAG('h', 'v', 'c', '1'):
return vpar->codec_id == AV_CODEC_ID_HEVC;
case FLV_CODECID_H263:
return vpar->codec_id == AV_CODEC_ID_FLV1;
case FLV_CODECID_SCREEN:
@ -326,12 +326,16 @@ static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
}
static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
int flv_codecid, int read)
uint32_t flv_codecid, int read)
{
int ret = 0;
AVCodecParameters *par = vstream->codecpar;
enum AVCodecID old_codec_id = vstream->codecpar->codec_id;
switch (flv_codecid) {
case MKBETAG('h', 'v', 'c', '1'):
par->codec_id = AV_CODEC_ID_HEVC;
vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
break;
case FLV_CODECID_H263:
par->codec_id = AV_CODEC_ID_FLV1;
break;
@ -363,11 +367,9 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
case FLV_CODECID_H264:
par->codec_id = AV_CODEC_ID_H264;
vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
ret = 3; // not 4, reading packet type will consume one byte
break;
case FLV_CODECID_MPEG4:
par->codec_id = AV_CODEC_ID_MPEG4;
ret = 3;
break;
default:
avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
@ -1022,6 +1024,8 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
AVStream *st = NULL;
int last = -1;
int orig_size;
uint32_t video_codec_id = 0;
int enhanced_flv = 0;
retry:
/* pkt size is repeated at end. skip it */
@ -1068,7 +1072,13 @@ retry:
} else if (type == FLV_TAG_TYPE_VIDEO) {
stream_type = FLV_STREAM_TYPE_VIDEO;
flags = avio_r8(s->pb);
video_codec_id = flags & FLV_VIDEO_CODECID_MASK;
size--;
enhanced_flv = (flags >> 7) & 1;
if (enhanced_flv) {
video_codec_id = avio_rb32(s->pb);
size -= 4;
}
if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD)
goto skip;
} else if (type == FLV_TAG_TYPE_META) {
@ -1126,7 +1136,7 @@ skip:
break;
} else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
(s->video_codec_id || flv_same_video_codec(st->codecpar, flags)))
(s->video_codec_id || flv_same_video_codec(st->codecpar, video_codec_id)))
break;
} else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
@ -1229,7 +1239,7 @@ retry_duration:
avcodec_parameters_free(&par);
}
} else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
int ret = flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1);
int ret = flv_set_video_codec(s, st, video_codec_id, 1);
if (ret < 0)
return ret;
size -= ret;
@ -1241,16 +1251,23 @@ retry_duration:
if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
st->codecpar->codec_id == AV_CODEC_ID_H264 ||
st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
int type = avio_r8(s->pb);
size--;
st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
int type = 0;
if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO) {
type = flags & 0x0F;
} else {
type = avio_r8(s->pb);
size--;
}
if (size < 0) {
ret = AVERROR_INVALIDDATA;
goto leave;
}
if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
(st->codecpar->codec_id == AV_CODEC_ID_HEVC && type == PacketTypeCodedFrames)) {
// sign extension
int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
pts = av_sat_add64(dts, cts);
@ -1264,9 +1281,10 @@ retry_duration:
"invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);
dts = pts = AV_NOPTS_VALUE;
}
size -= 3;
}
if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
st->codecpar->codec_id == AV_CODEC_ID_H264)) {
st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC)) {
AVDictionaryEntry *t;
if (st->codecpar->extradata) {

View File

@ -52,7 +52,7 @@ FF_CONFIG_OPTIONS="
--disable-bzlib
--disable-lzma
--disable-vulkan
--enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska
--enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska,flv
--enable-muxer=mp4,h264,ipod
--enable-parser=h263,h264,mpeg4video,vp8,vp9,mpegvideo
--enable-parser=mpegaudio,aac,aac_latm,av3a,amr
@ -139,7 +139,7 @@ FF_CONFIG_OPTIONS="
--disable-sdl2
--disable-bzlib
--disable-lzma
--enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska
--enable-demuxer=mp3,aac,ape,flac,ogg,wav,mov,mpegts,amr,amrnb,amrwb,matroska,flv
--enable-muxer=mp4,h264,ipod
--enable-parser=h263,h264,mpeg4video,vp8,vp9,mpegvideo
--enable-parser=mpegaudio,aac,aac_latm,av3a,amr