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
132enum {132enum {
133 AudioPacketTypeSequenceStart = 0,133 AudioPacketTypeSequenceStart = 0,
134 AudioPacketTypeCodedFrames = 1,134 AudioPacketTypeCodedFrames = 1,
135 AudioPacketTypeMultichannelConfig = 4,
136 AudioPacketTypeMultitrack = 5,
137};
138
139enum {
140 AudioChannelOrderUnspecified = 0,
141 AudioChannelOrderNative = 1,
142 AudioChannelOrderCustom = 2,
135};143};
136 144
137enum {145enum {
libavformat/flvdec.c+108−11
@@ -224,12 +224,33 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type, int track_idx · 223 unmodified lines
224 return st;224 return st;
225}225}
226 226
227static int flv_same_audio_codec(AVCodecParameters *apar, int flags)227static int flv_same_audio_codec(AVCodecParameters *apar, int flags, uint32_t codec_fourcc)
228{228{
229 int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;229 int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
230 int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;230 int flv_codecid = flags & FLV_AUDIO_CODECID_MASK;
231 int codec_id;231 int codec_id;
232 232
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
233 if (!apar->codec_id && !apar->codec_tag)254 if (!apar->codec_id && !apar->codec_tag)
234 return 1;255 return 1;
235 256
@@ -328,6 +349,24 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, · 92 unmodified lines
328 apar->sample_rate = 8000;349 apar->sample_rate = 8000;
329 apar->codec_id = AV_CODEC_ID_PCM_ALAW;350 apar->codec_id = AV_CODEC_ID_PCM_ALAW;
330 break;351 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;
331 default:370 default:
332 avpriv_request_sample(s, "Audio codec (%x)",371 avpriv_request_sample(s, "Audio codec (%x)",
333 flv_codecid >> FLV_AUDIO_CODECID_OFFSET);372 flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
@@ -1249,7 +1288,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) · 915 unmodified lines
1249 int multitrack = 0;1288 int multitrack = 0;
1250 int pkt_type = 0;1289 int pkt_type = 0;
1251 uint8_t track_idx = 0;1290 uint8_t track_idx = 0;
1252 uint32_t video_codec_id = 0;1291 uint32_t codec_id = 0;
1253 1292
1254retry:1293retry:
1255 /* pkt size is repeated at end. skip it */1294 /* pkt size is repeated at end. skip it */
@@ -1293,16 +1332,31 @@ retry: · 37 unmodified lines
1293 stream_type = FLV_STREAM_TYPE_AUDIO;1332 stream_type = FLV_STREAM_TYPE_AUDIO;
1294 flags = avio_r8(s->pb);1333 flags = avio_r8(s->pb);
1295 size--;1334 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 }
1296 } else if (type == FLV_TAG_TYPE_VIDEO) {1350 } else if (type == FLV_TAG_TYPE_VIDEO) {
1297 stream_type = FLV_STREAM_TYPE_VIDEO;1351 stream_type = FLV_STREAM_TYPE_VIDEO;
1298 flags = avio_r8(s->pb);1352 flags = avio_r8(s->pb);
1299 video_codec_id = flags & FLV_VIDEO_CODECID_MASK;1353 codec_id = flags & FLV_VIDEO_CODECID_MASK;
1300 /*1354 /*
1301 * Reference Enhancing FLV 2023-03-v1.0.0-B.81355 * Reference Enhancing FLV 2023-03-v1.0.0-B.8
1302 * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf1356 * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf
1303 * */1357 * */
1304 enhanced_flv = (flags >> 7) & 1;1358 enhanced_flv = (flags >> 7) & 1;
1305 pkt_type = enhanced_flv ? video_codec_id : 0;1359 pkt_type = enhanced_flv ? codec_id : 0;
1306 size--;1360 size--;
1307 1361
1308 if (pkt_type == PacketTypeMultitrack) {1362 if (pkt_type == PacketTypeMultitrack) {
@@ -1320,7 +1374,7 @@ retry: · 11 unmodified lines
1320 }1374 }
1321 1375
1322 if (enhanced_flv) {1376 if (enhanced_flv) {
1323 video_codec_id = avio_rb32(s->pb);1377 codec_id = avio_rb32(s->pb);
1324 size -= 4;1378 size -= 4;
1325 }1379 }
1326 if (multitrack) {1380 if (multitrack) {
@@ -1388,11 +1442,11 @@ skip: · 61 unmodified lines
1388 st = s->streams[i];1442 st = s->streams[i];
1389 if (stream_type == FLV_STREAM_TYPE_AUDIO) {1443 if (stream_type == FLV_STREAM_TYPE_AUDIO) {
1390 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&1444 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)))
1392 break;1446 break;
1393 } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {1447 } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
1394 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&1448 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)) &&
1396 st->id == track_idx)1450 st->id == track_idx)
1397 break;1451 break;
1398 } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {1452 } else if (stream_type == FLV_STREAM_TYPE_SUBTITLE) {
@@ -1461,7 +1515,7 @@ retry_duration: · 62 unmodified lines
1461 flv->searched_for_end = 1;1515 flv->searched_for_end = 1;
1462 }1516 }
1463 1517
1464 if (stream_type == FLV_STREAM_TYPE_AUDIO) {1518 if (stream_type == FLV_STREAM_TYPE_AUDIO && !enhanced_flv) {
1465 int bits_per_coded_sample;1519 int bits_per_coded_sample;
1466 channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;1520 channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1;
1467 sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>1521 sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
@@ -1493,8 +1547,48 @@ retry_duration: · 25 unmodified lines
1493 sample_rate = par->sample_rate;1547 sample_rate = par->sample_rate;
1494 avcodec_parameters_free(&par);1548 avcodec_parameters_free(&par);
1495 }1549 }
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 }
1496 } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {1590 } 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);
1498 if (ret < 0)1592 if (ret < 0)
1499 return ret;1593 return ret;
1500 size -= ret;1594 size -= ret;
@@ -1505,13 +1599,15 @@ retry_duration: · 4 unmodified lines
1505 }1599 }
1506 1600
1507 if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||1601 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 ||
1508 st->codecpar->codec_id == AV_CODEC_ID_H264 ||1604 st->codecpar->codec_id == AV_CODEC_ID_H264 ||
1509 st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||1605 st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
1510 st->codecpar->codec_id == AV_CODEC_ID_HEVC ||1606 st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
1511 st->codecpar->codec_id == AV_CODEC_ID_AV1 ||1607 st->codecpar->codec_id == AV_CODEC_ID_AV1 ||
1512 st->codecpar->codec_id == AV_CODEC_ID_VP9) {1608 st->codecpar->codec_id == AV_CODEC_ID_VP9) {
1513 int type = 0;1609 int type = 0;
1514 if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO) {1610 if (enhanced_flv) {
1515 type = pkt_type;1611 type = pkt_type;
1516 } else {1612 } else {
1517 type = avio_r8(s->pb);1613 type = avio_r8(s->pb);
@@ -1547,6 +1643,7 @@ retry_duration: · 29 unmodified lines
1547 size -= 3;1643 size -= 3;
1548 }1644 }
1549 if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||1645 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 ||
1550 st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC ||1647 st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_HEVC ||
1551 st->codecpar->codec_id == AV_CODEC_ID_AV1 || st->codecpar->codec_id == AV_CODEC_ID_VP9)) {1648 st->codecpar->codec_id == AV_CODEC_ID_AV1 || st->codecpar->codec_id == AV_CODEC_ID_VP9)) {
1552 AVDictionaryEntry *t;1649 AVDictionaryEntry *t;
@@ -1602,7 +1699,7 @@ retry_duration: · 49 unmodified lines
1602 flv->mt_extradata_sz[track_idx] = 0;1699 flv->mt_extradata_sz[track_idx] = 0;
1603 }1700 }
1604 }1701 }
1605 if (stream_type == FLV_STREAM_TYPE_AUDIO &&1702 if (stream_type == FLV_STREAM_TYPE_AUDIO && !enhanced_flv &&
1606 (sample_rate != flv->last_sample_rate ||1703 (sample_rate != flv->last_sample_rate ||
1607 channels != flv->last_channels)) {1704 channels != flv->last_channels)) {
1608 flv->last_sample_rate = sample_rate;1705 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