| @@ -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 | |
| 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) |
| 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 | |
| 1254 | retry: | 1293 | retry: |
| 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.8 | 1355 | * Reference Enhancing FLV 2023-03-v1.0.0-B.8 |
| 1302 | * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp-v1.pdf | 1356 | * 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; |