forked from FFmpeg/FFmpeg
avformat/flvdec: add enhanced audio codecs
This commit is contained in:
parent
70067c829b
commit
2f72dc33ff
2 changed files with 116 additions and 11 deletions
|
@ -132,6 +132,14 @@ enum {
|
|||
enum {
|
||||
AudioPacketTypeSequenceStart = 0,
|
||||
AudioPacketTypeCodedFrames = 1,
|
||||
AudioPacketTypeMultichannelConfig = 4,
|
||||
AudioPacketTypeMultitrack = 5,
|
||||
};
|
||||
|
||||
enum {
|
||||
AudioChannelOrderUnspecified = 0,
|
||||
AudioChannelOrderNative = 1,
|
||||
AudioChannelOrderCustom = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
@ -224,12 +224,33 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type, int track_idx
|
|||
return st;
|
||||
}
|
||||
|
||||
static int flv_same_audio_codec(AVCodecParameters *apar, int flags)
|
||||
static int flv_same_audio_codec(AVCodecParameters *apar, int flags, uint32_t codec_fourcc)
|
||||
{
|
||||
int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
|
||||
int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;
|
||||
int codec_id;
|
||||
|
||||
switch (codec_fourcc) {
|
||||
case MKBETAG('m', 'p', '4', 'a'):
|
||||
return apar->codec_id == AV_CODEC_ID_AAC;
|
||||
case MKBETAG('O', 'p', 'u', 's'):
|
||||
return apar->codec_id == AV_CODEC_ID_OPUS;
|
||||
case MKBETAG('.', 'm', 'p', '3'):
|
||||
return apar->codec_id == AV_CODEC_ID_MP3;
|
||||
case MKBETAG('f', 'L', 'a', 'C'):
|
||||
return apar->codec_id == AV_CODEC_ID_FLAC;
|
||||
case MKBETAG('a', 'c', '-', '3'):
|
||||
return apar->codec_id == AV_CODEC_ID_AC3;
|
||||
case MKBETAG('e', 'c', '-', '3'):
|
||||
return apar->codec_id == AV_CODEC_ID_EAC3;
|
||||
case 0:
|
||||
// Not enhanced flv, continue as normal.
|
||||
break;
|
||||
default:
|
||||
// Unknown FOURCC
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!apar->codec_id && !apar->codec_tag)
|
||||
return 1;
|
||||
|
||||
|
@ -328,6 +349,24 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
|
|||
apar->sample_rate = 8000;
|
||||
apar->codec_id = AV_CODEC_ID_PCM_ALAW;
|
||||
break;
|
||||
case MKBETAG('m', 'p', '4', 'a'):
|
||||
apar->codec_id = AV_CODEC_ID_AAC;
|
||||
return;
|
||||
case MKBETAG('O', 'p', 'u', 's'):
|
||||
apar->codec_id = AV_CODEC_ID_OPUS;
|
||||
return;
|
||||
case MKBETAG('.', 'm', 'p', '3'):
|
||||
apar->codec_id = AV_CODEC_ID_MP3;
|
||||
return;
|
||||
case MKBETAG('f', 'L', 'a', 'C'):
|
||||
apar->codec_id = AV_CODEC_ID_FLAC;
|
||||
return;
|
||||
case MKBETAG('a', 'c', '-', '3'):
|
||||
apar->codec_id = AV_CODEC_ID_AC3;
|
||||
return;
|
||||
case MKBETAG('e', 'c', '-', '3'):
|
||||
apar->codec_id = AV_CODEC_ID_EAC3;
|
||||
return;
|
||||
default:
|
||||
avpriv_request_sample(s, "Audio codec (%x)",
|
||||
flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
|
||||
|
@ -1249,7 +1288,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||
int multitrack = 0;
|
||||
int pkt_type = 0;
|
||||
uint8_t track_idx = 0;
|
||||
uint32_t video_codec_id = 0;
|
||||
uint32_t codec_id = 0;
|
||||
|
||||
retry:
|
||||
/* pkt size is repeated at end. skip it */
|
||||
|
@ -1293,16 +1332,31 @@ retry:
|
|||
stream_type = FLV_STREAM_TYPE_AUDIO;
|
||||
flags = avio_r8(s->pb);
|
||||
size--;
|
||||
|
||||
if ((flags & FLV_AUDIO_CODECID_MASK) == FLV_CODECID_EX_HEADER) {
|
||||
enhanced_flv = 1;
|
||||
pkt_type = flags & ~FLV_AUDIO_CODECID_MASK;
|
||||
|
||||
channels = 0;
|
||||
|
||||
if (pkt_type == AudioPacketTypeMultitrack) {
|
||||
av_log(s, AV_LOG_ERROR, "Multitrack audio is unsupported!\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
codec_id = avio_rb32(s->pb);
|
||||
size -= 4;
|
||||
}
|
||||
} 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;
|
||||
codec_id = flags & FLV_VIDEO_CODECID_MASK;
|
||||
/*
|
||||
* Reference Enhancing FLV 2023-03-v1.0.0-B.8
|
||||
* https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
|
||||
* */
|
||||
enhanced_flv = (flags >> 7) & 1;
|
||||
pkt_type = enhanced_flv ? video_codec_id : 0;
|
||||
pkt_type = enhanced_flv ? codec_id : 0;
|
||||
size--;
|
||||
|
||||
if (pkt_type == PacketTypeMultitrack) {
|
||||
|
@ -1320,7 +1374,7 @@ retry:
|
|||
}
|
||||
|
||||
if (enhanced_flv) {
|
||||
video_codec_id = avio_rb32(s->pb);
|
||||
codec_id = avio_rb32(s->pb);
|
||||
size -= 4;
|
||||
}
|
||||
if (multitrack) {
|
||||
|
@ -1388,11 +1442,11 @@ skip:
|
|||
st = s->streams[i];
|
||||
if (stream_type == FLV_STREAM_TYPE_AUDIO) {
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
|
||||
(s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags)))
|
||||
(s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags, codec_id)))
|
||||
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, video_codec_id)) &&
|
||||
(s->video_codec_id || flv_same_video_codec(st->codecpar, codec_id)) &&
|
||||
st->id == track_idx)
|
||||
break;
|
||||
} else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
|
||||
|
@ -1461,7 +1515,7 @@ retry_duration:
|
|||
flv->searched_for_end = 1;
|
||||
}
|
||||
|
||||
if (stream_type == FLV_STREAM_TYPE_AUDIO) {
|
||||
if (stream_type == FLV_STREAM_TYPE_AUDIO && !enhanced_flv) {
|
||||
int bits_per_coded_sample;
|
||||
channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
|
||||
sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
|
||||
|
@ -1493,8 +1547,48 @@ retry_duration:
|
|||
sample_rate = par->sample_rate;
|
||||
avcodec_parameters_free(&par);
|
||||
}
|
||||
} else if (stream_type == FLV_STREAM_TYPE_AUDIO) {
|
||||
if (!st->codecpar->codec_id) {
|
||||
flv_set_audio_codec(s, st, st->codecpar,
|
||||
codec_id ? codec_id : (flags & FLV_AUDIO_CODECID_MASK));
|
||||
flv->last_sample_rate = 0;
|
||||
flv->last_channels = 0;
|
||||
}
|
||||
|
||||
// These are not signalled in the flags anymore
|
||||
channels = 0;
|
||||
sample_rate = 0;
|
||||
|
||||
if (pkt_type == AudioPacketTypeMultichannelConfig) {
|
||||
int channel_order = avio_r8(s->pb);
|
||||
channels = avio_r8(s->pb);
|
||||
size -= 2;
|
||||
|
||||
if (channel_order == AudioChannelOrderCustom) {
|
||||
for (i = 0; i < channels; i++) {
|
||||
avio_r8(s->pb); // audio channel mapping
|
||||
size--;
|
||||
}
|
||||
} else if (channel_order == AudioChannelOrderNative) {
|
||||
avio_rb32(s->pb); // audio channel flags
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
if (!av_channel_layout_check(&st->codecpar->ch_layout)) {
|
||||
///TODO: This can be much more sophisticated with above info.
|
||||
av_channel_layout_default(&st->codecpar->ch_layout, channels);
|
||||
flv->last_channels = channels;
|
||||
}
|
||||
|
||||
if (channels != flv->last_channels) {
|
||||
flv->last_channels = channels;
|
||||
ff_add_param_change(pkt, channels, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
goto leave;
|
||||
}
|
||||
} else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
|
||||
int ret = flv_set_video_codec(s, st, video_codec_id, 1);
|
||||
int ret = flv_set_video_codec(s, st, codec_id, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
size -= ret;
|
||||
|
@ -1505,13 +1599,15 @@ retry_duration:
|
|||
}
|
||||
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_OPUS ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_FLAC ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_H264 ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_AV1 ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_VP9) {
|
||||
int type = 0;
|
||||
if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO) {
|
||||
if (enhanced_flv) {
|
||||
type = pkt_type;
|
||||
} else {
|
||||
type = avio_r8(s->pb);
|
||||
|
@ -1547,6 +1643,7 @@ retry_duration:
|
|||
size -= 3;
|
||||
}
|
||||
if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_OPUS || st->codecpar->codec_id == AV_CODEC_ID_FLAC ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
|
||||
st->codecpar->codec_id == AV_CODEC_ID_AV1 || st->codecpar->codec_id == AV_CODEC_ID_VP9)) {
|
||||
AVDictionaryEntry *t;
|
||||
|
@ -1602,7 +1699,7 @@ retry_duration:
|
|||
flv->mt_extradata_sz[track_idx] = 0;
|
||||
}
|
||||
}
|
||||
if (stream_type == FLV_STREAM_TYPE_AUDIO &&
|
||||
if (stream_type == FLV_STREAM_TYPE_AUDIO && !enhanced_flv &&
|
||||
(sample_rate != flv->last_sample_rate ||
|
||||
channels != flv->last_channels)) {
|
||||
flv->last_sample_rate = sample_rate;
|
||||
|
|
Loading…
Add table
Reference in a new issue