| @@ -1279,6 +1279,62 @@ static int flv_update_video_color_info(AVFormatContext *s, AVStream *st) · 1278 unmodified lines |
| 1279 | 1279 | return 0; |
| 1280 | 1280 | } |
| 1281 | 1281 | |
| 1282 | +static int flv_parse_mod_ex_data(AVFormatContext *s, int *pkt_type, int *size, int64_t *dts) |
| 1283 | +{ |
| 1284 | + int ex_type, ret; |
| 1285 | + uint8_t *ex_data; |
| 1286 | + |
| 1287 | + int ex_size = (uint8_t)avio_r8(s->pb) + 1; |
| 1288 | + *size -= 1; |
| 1289 | + |
| 1290 | + if (ex_size == 256) { |
| 1291 | + ex_size = (uint16_t)avio_rb16(s->pb) + 1; |
| 1292 | + *size -= 2; |
| 1293 | + } |
| 1294 | + |
| 1295 | + if (ex_size >= *size) { |
| 1296 | + av_log(s, AV_LOG_WARNING, "ModEx size larger than remaining data!\n"); |
| 1297 | + return AVERROR(EINVAL); |
| 1298 | + } |
| 1299 | + |
| 1300 | + ex_data = av_malloc(ex_size); |
| 1301 | + if (!ex_data) |
| 1302 | + return AVERROR(ENOMEM); |
| 1303 | + |
| 1304 | + ret = avio_read(s->pb, ex_data, ex_size); |
| 1305 | + if (ret < 0) { |
| 1306 | + av_free(ex_data); |
| 1307 | + return ret; |
| 1308 | + } |
| 1309 | + *size -= ex_size; |
| 1310 | + |
| 1311 | + ex_type = (uint8_t)avio_r8(s->pb); |
| 1312 | + *size -= 1; |
| 1313 | + |
| 1314 | + *pkt_type = ex_type & 0x0f; |
| 1315 | + ex_type &= 0xf0; |
| 1316 | + |
| 1317 | + if (ex_type == PacketModExTypeTimestampOffsetNano) { |
| 1318 | + uint32_t nano_offset; |
| 1319 | + |
| 1320 | + if (ex_size != 3) { |
| 1321 | + av_log(s, AV_LOG_WARNING, "Invalid ModEx size for Type TimestampOffsetNano!\n"); |
| 1322 | + nano_offset = 0; |
| 1323 | + } else { |
| 1324 | + nano_offset = (ex_data[0] << 16) | (ex_data[1] << 8) | ex_data[2]; |
| 1325 | + } |
| 1326 | + |
| 1327 | + // this is not likely to ever add anything, but right now timestamps are with ms precision |
| 1328 | + *dts += nano_offset / 1000000; |
| 1329 | + } else { |
| 1330 | + av_log(s, AV_LOG_INFO, "Unknown ModEx type: %d", ex_type); |
| 1331 | + } |
| 1332 | + |
| 1333 | + av_free(ex_data); |
| 1334 | + |
| 1335 | + return 0; |
| 1336 | +} |
| 1337 | + |
| 1282 | 1338 | static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) |
| 1283 | 1339 | { |
| 1284 | 1340 | FLVContext *flv = s->priv_data; |
| @@ -1347,6 +1403,12 @@ retry: · 62 unmodified lines |
| 1347 | 1403 | enhanced_flv = 1; |
| 1348 | 1404 | pkt_type = flags & ~FLV_AUDIO_CODECID_MASK; |
| 1349 | 1405 | |
| 1406 | + while (pkt_type == PacketTypeModEx) { |
| 1407 | + ret = flv_parse_mod_ex_data(s, &pkt_type, &size, &dts); |
| 1408 | + if (ret < 0) |
| 1409 | + goto leave; |
| 1410 | + } |
| 1411 | + |
| 1350 | 1412 | if (pkt_type == AudioPacketTypeMultitrack) { |
| 1351 | 1413 | uint8_t types = avio_r8(s->pb); |
| 1352 | 1414 | multitrack_type = types & 0xF0; |
| @@ -1376,6 +1438,12 @@ retry: · 23 unmodified lines |
| 1376 | 1438 | pkt_type = enhanced_flv ? codec_id : 0; |
| 1377 | 1439 | size--; |
| 1378 | 1440 | |
| 1441 | + while (pkt_type == PacketTypeModEx) { |
| 1442 | + ret = flv_parse_mod_ex_data(s, &pkt_type, &size, &dts); |
| 1443 | + if (ret < 0) |
| 1444 | + goto leave; |
| 1445 | + } |
| 1446 | + |
| 1379 | 1447 | if (pkt_type == PacketTypeMultitrack) { |
| 1380 | 1448 | uint8_t types = avio_r8(s->pb); |
| 1381 | 1449 | multitrack_type = types & 0xF0; |