History

avformat/flvdec: add enhanced audio codecs

Timo Rothenpieler committed 2 years ago

Commit 2f72dc31 parent 70067c82 files · +116 −11Browse files

Unified · Split

2 files
  1. libavformat/flv.h +8 −0
  2. libavformat/flvdec.c +108 −11
libavformat/flv.h+8−0
@@ -132,6 +132,14 @@ enum { · 131 unmodified lines
132132 enum {
133133 AudioPacketTypeSequenceStart = 0,
134134 AudioPacketTypeCodedFrames = 1,
135+ AudioPacketTypeMultichannelConfig = 4,
136+ AudioPacketTypeMultitrack = 5,
137+};
138+
139+enum {
140+ AudioChannelOrderUnspecified = 0,
141+ AudioChannelOrderNative = 1,
142+ AudioChannelOrderCustom = 2,
135143 };
136144
137145 enum {
libavformat/flvdec.c+108−11
@@ -224,12 +224,33 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type, int track_idx · 223 unmodified lines
224224 return st;
225225 }
226226
227−static int flv_same_audio_codec(AVCodecParameters *apar, int flags)
227+static int flv_same_audio_codec(AVCodecParameters *apar, int flags, uint32_t codec_fourcc)
228228 {
229229 int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
230230 int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;
231231 int codec_id;
232232
233+ switch (codec_fourcc) {
234+ case MKBETAG('m', 'p', '4', 'a'):
235+ return apar->codec_id == AV_CODEC_ID_AAC;
236+ case MKBETAG('O', 'p', 'u', 's'):
237+ return apar->codec_id == AV_CODEC_ID_OPUS;
238+ case MKBETAG('.', 'm', 'p', '3'):
239+ return apar->codec_id == AV_CODEC_ID_MP3;
240+ case MKBETAG('f', 'L', 'a', 'C'):
241+ return apar->codec_id == AV_CODEC_ID_FLAC;
242+ case MKBETAG('a', 'c', '-', '3'):
243+ return apar->codec_id == AV_CODEC_ID_AC3;
244+ case MKBETAG('e', 'c', '-', '3'):
245+ return apar->codec_id == AV_CODEC_ID_EAC3;
246+ case 0:
247+ // Not enhanced flv, continue as normal.
248+ break;
249+ default:
250+ // Unknown FOURCC
251+ return 0;
252+ }
253+
233254 if (!apar->codec_id && !apar->codec_tag)
234255 return 1;
235256
@@ -328,6 +349,24 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, · 92 unmodified lines
328349 apar->sample_rate = 8000;
329350 apar->codec_id = AV_CODEC_ID_PCM_ALAW;
330351 break;
352+ case MKBETAG('m', 'p', '4', 'a'):
353+ apar->codec_id = AV_CODEC_ID_AAC;
354+ return;
355+ case MKBETAG('O', 'p', 'u', 's'):
356+ apar->codec_id = AV_CODEC_ID_OPUS;
357+ return;
358+ case MKBETAG('.', 'm', 'p', '3'):
359+ apar->codec_id = AV_CODEC_ID_MP3;
360+ return;
361+ case MKBETAG('f', 'L', 'a', 'C'):
362+ apar->codec_id = AV_CODEC_ID_FLAC;
363+ return;
364+ case MKBETAG('a', 'c', '-', '3'):
365+ apar->codec_id = AV_CODEC_ID_AC3;
366+ return;
367+ case MKBETAG('e', 'c', '-', '3'):
368+ apar->codec_id = AV_CODEC_ID_EAC3;
369+ return;
331370 default:
332371 avpriv_request_sample(s, "Audio codec (%x)",
333372 flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
@@ -1249,7 +1288,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) · 915 unmodified lines
12491288 int multitrack = 0;
12501289 int pkt_type = 0;
12511290 uint8_t track_idx = 0;
1252− uint32_t video_codec_id = 0;
1291+ uint32_t codec_id = 0;
12531292
12541293 retry:
12551294 /* pkt size is repeated at end. skip it */
@@ -1293,16 +1332,31 @@ retry: · 37 unmodified lines
12931332 stream_type = FLV_STREAM_TYPE_AUDIO;
12941333 flags = avio_r8(s->pb);
12951334 size--;
1335+
1336+ if ((flags & FLV_AUDIO_CODECID_MASK) == FLV_CODECID_EX_HEADER) {
1337+ enhanced_flv = 1;
1338+ pkt_type = flags & ~FLV_AUDIO_CODECID_MASK;
1339+
1340+ channels = 0;
1341+
1342+ if (pkt_type == AudioPacketTypeMultitrack) {
1343+ av_log(s, AV_LOG_ERROR, "Multitrack audio is unsupported!\n");
1344+ return AVERROR_PATCHWELCOME;
1345+ }
1346+
1347+ codec_id = avio_rb32(s->pb);
1348+ size -= 4;
1349+ }
12961350 } else if (type == FLV_TAG_TYPE_VIDEO) {
12971351 stream_type = FLV_STREAM_TYPE_VIDEO;
12981352 flags = avio_r8(s->pb);
1299− video_codec_id = flags & FLV_VIDEO_CODECID_MASK;
1353+ codec_id = flags & FLV_VIDEO_CODECID_MASK;
13001354 /*
13011355 * Reference Enhancing FLV 2023-03-v1.0.0-B.8
13021356 * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
13031357 * */
13041358 enhanced_flv = (flags >> 7) & 1;
1305− pkt_type = enhanced_flv ? video_codec_id : 0;
1359+ pkt_type = enhanced_flv ? codec_id : 0;
13061360 size--;
13071361
13081362 if (pkt_type == PacketTypeMultitrack) {
@@ -1320,7 +1374,7 @@ retry: · 11 unmodified lines
13201374 }
13211375
13221376 if (enhanced_flv) {
1323− video_codec_id = avio_rb32(s->pb);
1377+ codec_id = avio_rb32(s->pb);
13241378 size -= 4;
13251379 }
13261380 if (multitrack) {
@@ -1388,11 +1442,11 @@ skip: · 61 unmodified lines
13881442 st = s->streams[i];
13891443 if (stream_type == FLV_STREAM_TYPE_AUDIO) {
13901444 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
1391− (s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags)))
1445+ (s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags, codec_id)))
13921446 break;
13931447 } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
13941448 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
1395− (s->video_codec_id || flv_same_video_codec(st->codecpar, video_codec_id)) &&
1449+ (s->video_codec_id || flv_same_video_codec(st->codecpar, codec_id)) &&
13961450 st->id == track_idx)
13971451 break;
13981452 } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
@@ -1461,7 +1515,7 @@ retry_duration: · 62 unmodified lines
14611515 flv->searched_for_end = 1;
14621516 }
14631517
1464− if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1518+ if (stream_type == FLV_STREAM_TYPE_AUDIO && !enhanced_flv) {
14651519 int bits_per_coded_sample;
14661520 channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
14671521 sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
@@ -1493,8 +1547,48 @@ retry_duration: · 25 unmodified lines
14931547 sample_rate = par->sample_rate;
14941548 avcodec_parameters_free(&par);
14951549 }
1550+ } else if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1551+ if (!st->codecpar->codec_id) {
1552+ flv_set_audio_codec(s, st, st->codecpar,
1553+ codec_id ? codec_id : (flags & FLV_AUDIO_CODECID_MASK));
1554+ flv->last_sample_rate = 0;
1555+ flv->last_channels = 0;
1556+ }
1557+
1558+ // These are not signalled in the flags anymore
1559+ channels = 0;
1560+ sample_rate = 0;
1561+
1562+ if (pkt_type == AudioPacketTypeMultichannelConfig) {
1563+ int channel_order = avio_r8(s->pb);
1564+ channels = avio_r8(s->pb);
1565+ size -= 2;
1566+
1567+ if (channel_order == AudioChannelOrderCustom) {
1568+ for (i = 0; i < channels; i++) {
1569+ avio_r8(s->pb); // audio channel mapping
1570+ size--;
1571+ }
1572+ } else if (channel_order == AudioChannelOrderNative) {
1573+ avio_rb32(s->pb); // audio channel flags
1574+ size -= 4;
1575+ }
1576+
1577+ if (!av_channel_layout_check(&st->codecpar->ch_layout)) {
1578+ ///TODO: This can be much more sophisticated with above info.
1579+ av_channel_layout_default(&st->codecpar->ch_layout, channels);
1580+ flv->last_channels = channels;
1581+ }
1582+
1583+ if (channels != flv->last_channels) {
1584+ flv->last_channels = channels;
1585+ ff_add_param_change(pkt, channels, 0, 0, 0, 0);
1586+ }
1587+
1588+ goto leave;
1589+ }
14961590 } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
1497− int ret = flv_set_video_codec(s, st, video_codec_id, 1);
1591+ int ret = flv_set_video_codec(s, st, codec_id, 1);
14981592 if (ret < 0)
14991593 return ret;
15001594 size -= ret;
@@ -1505,13 +1599,15 @@ retry_duration: · 4 unmodified lines
15051599 }
15061600
15071601 if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
1602+ st->codecpar->codec_id == AV_CODEC_ID_OPUS ||
1603+ st->codecpar->codec_id == AV_CODEC_ID_FLAC ||
15081604 st->codecpar->codec_id == AV_CODEC_ID_H264 ||
15091605 st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
15101606 st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
15111607 st->codecpar->codec_id == AV_CODEC_ID_AV1 ||
15121608 st->codecpar->codec_id == AV_CODEC_ID_VP9) {
15131609 int type = 0;
1514− if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO) {
1610+ if (enhanced_flv) {
15151611 type = pkt_type;
15161612 } else {
15171613 type = avio_r8(s->pb);
@@ -1547,6 +1643,7 @@ retry_duration: · 29 unmodified lines
15471643 size -= 3;
15481644 }
15491645 if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
1646+ st->codecpar->codec_id == AV_CODEC_ID_OPUS || st->codecpar->codec_id == AV_CODEC_ID_FLAC ||
15501647 st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
15511648 st->codecpar->codec_id == AV_CODEC_ID_AV1 || st->codecpar->codec_id == AV_CODEC_ID_VP9)) {
15521649 AVDictionaryEntry *t;
@@ -1602,7 +1699,7 @@ retry_duration: · 49 unmodified lines
16021699 flv->mt_extradata_sz[track_idx] = 0;
16031700 }
16041701 }
1605− if (stream_type == FLV_STREAM_TYPE_AUDIO &&
1702+ if (stream_type == FLV_STREAM_TYPE_AUDIO && !enhanced_flv &&
16061703 (sample_rate != flv->last_sample_rate ||
16071704 channels != flv->last_channels)) {
16081705 flv->last_sample_rate = sample_rate;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t