winlin

for #383, refine code to support mix correct algorithm.

@@ -75,7 +75,7 @@ heartbeat { @@ -75,7 +75,7 @@ heartbeat {
75 # the id of devide. 75 # the id of devide.
76 device_id "my-srs-device"; 76 device_id "my-srs-device";
77 # whether report with summaries 77 # whether report with summaries
78 - # if true, put /api/v1/summaries to the request data: 78 + # if on, put /api/v1/summaries to the request data:
79 # { 79 # {
80 # "summaries": summaries object. 80 # "summaries": summaries object.
81 # } 81 # }
@@ -1338,6 +1338,11 @@ vhost jitter.srs.com { @@ -1338,6 +1338,11 @@ vhost jitter.srs.com {
1338 # 3. off, disable the time jitter algorithm, like atc. 1338 # 3. off, disable the time jitter algorithm, like atc.
1339 # default: full 1339 # default: full
1340 time_jitter full; 1340 time_jitter full;
  1341 + # whether use the mix algorithm to correct the timestamp.
  1342 + # if on, always ensure the timestamp of audio+video is monotonically increase.
  1343 + # if off, use time_jitter to correct the timestamp if required.
  1344 + # default: off
  1345 + mix_correct off;
1341 } 1346 }
1342 1347
1343 # vhost for atc. 1348 # vhost for atc.
@@ -171,7 +171,7 @@ int do_proxy(srs_flv_t flv, srs_rtmp_t ortmp, int64_t re, int32_t* pstarttime, u @@ -171,7 +171,7 @@ int do_proxy(srs_flv_t flv, srs_rtmp_t ortmp, int64_t re, int32_t* pstarttime, u
171 return ret; 171 return ret;
172 } 172 }
173 173
174 - if (*pstarttime < 0) { 174 + if (*pstarttime < 0 && srs_utils_flv_tag_is_av(type)) {
175 *pstarttime = *ptimestamp; 175 *pstarttime = *ptimestamp;
176 } 176 }
177 177
@@ -1332,8 +1332,17 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1332,8 +1332,17 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1332 } 1332 }
1333 srs_verbose("initialize shared ptr audio success."); 1333 srs_verbose("initialize shared ptr audio success.");
1334 1334
  1335 + srs_warn("Audio dts=%"PRId64", size=%d", msg.timestamp, msg.size);
  1336 +
  1337 + return on_audio_imp(&msg);
  1338 +}
  1339 +
  1340 +int SrsSource::on_audio_imp(SrsSharedPtrMessage* msg)
  1341 +{
  1342 + int ret = ERROR_SUCCESS;
  1343 +
1335 #ifdef SRS_AUTO_HLS 1344 #ifdef SRS_AUTO_HLS
1336 - if ((ret = hls->on_audio(&msg)) != ERROR_SUCCESS) { 1345 + if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) {
1337 // apply the error strategy for hls. 1346 // apply the error strategy for hls.
1338 // @see https://github.com/winlinvip/simple-rtmp-server/issues/264 1347 // @see https://github.com/winlinvip/simple-rtmp-server/issues/264
1339 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost); 1348 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost);
@@ -1347,7 +1356,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1347,7 +1356,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1347 ret = ERROR_SUCCESS; 1356 ret = ERROR_SUCCESS;
1348 } else if (hls_error_strategy == SRS_CONF_DEFAULT_HLS_ON_ERROR_CONTINUE) { 1357 } else if (hls_error_strategy == SRS_CONF_DEFAULT_HLS_ON_ERROR_CONTINUE) {
1349 // compare the sequence header with audio, continue when it's actually an sequence header. 1358 // compare the sequence header with audio, continue when it's actually an sequence header.
1350 - if (ret == ERROR_HLS_DECODE_ERROR && cache_sh_audio && cache_sh_audio->size == msg.size) { 1359 + if (ret == ERROR_HLS_DECODE_ERROR && cache_sh_audio && cache_sh_audio->size == msg->size) {
1351 srs_warn("the audio is actually a sequence header, ignore this packet."); 1360 srs_warn("the audio is actually a sequence header, ignore this packet.");
1352 ret = ERROR_SUCCESS; 1361 ret = ERROR_SUCCESS;
1353 } else { 1362 } else {
@@ -1362,7 +1371,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1362,7 +1371,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1362 #endif 1371 #endif
1363 1372
1364 #ifdef SRS_AUTO_DVR 1373 #ifdef SRS_AUTO_DVR
1365 - if ((ret = dvr->on_audio(&msg)) != ERROR_SUCCESS) { 1374 + if ((ret = dvr->on_audio(msg)) != ERROR_SUCCESS) {
1366 srs_warn("dvr process audio message failed, ignore and disable dvr. ret=%d", ret); 1375 srs_warn("dvr process audio message failed, ignore and disable dvr. ret=%d", ret);
1367 1376
1368 // unpublish, ignore ret. 1377 // unpublish, ignore ret.
@@ -1374,7 +1383,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1374,7 +1383,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1374 #endif 1383 #endif
1375 1384
1376 #ifdef SRS_AUTO_HDS 1385 #ifdef SRS_AUTO_HDS
1377 - if ((ret = hds->on_audio(&msg)) != ERROR_SUCCESS) { 1386 + if ((ret = hds->on_audio(msg)) != ERROR_SUCCESS) {
1378 srs_warn("hds process audio message failed, ignore and disable dvr. ret=%d", ret); 1387 srs_warn("hds process audio message failed, ignore and disable dvr. ret=%d", ret);
1379 1388
1380 // unpublish, ignore ret. 1389 // unpublish, ignore ret.
@@ -1390,7 +1399,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1390,7 +1399,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1390 SrsConsumer** pconsumer = consumers.data(); 1399 SrsConsumer** pconsumer = consumers.data();
1391 for (int i = 0; i < nb_consumers; i++) { 1400 for (int i = 0; i < nb_consumers; i++) {
1392 SrsConsumer* consumer = pconsumer[i]; 1401 SrsConsumer* consumer = pconsumer[i];
1393 - if ((ret = consumer->enqueue(&msg, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { 1402 + if ((ret = consumer->enqueue(msg, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) {
1394 srs_error("dispatch the audio failed. ret=%d", ret); 1403 srs_error("dispatch the audio failed. ret=%d", ret);
1395 return ret; 1404 return ret;
1396 } 1405 }
@@ -1403,7 +1412,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1403,7 +1412,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1403 std::vector<SrsForwarder*>::iterator it; 1412 std::vector<SrsForwarder*>::iterator it;
1404 for (it = forwarders.begin(); it != forwarders.end(); ++it) { 1413 for (it = forwarders.begin(); it != forwarders.end(); ++it) {
1405 SrsForwarder* forwarder = *it; 1414 SrsForwarder* forwarder = *it;
1406 - if ((ret = forwarder->on_audio(&msg)) != ERROR_SUCCESS) { 1415 + if ((ret = forwarder->on_audio(msg)) != ERROR_SUCCESS) {
1407 srs_error("forwarder process audio message failed. ret=%d", ret); 1416 srs_error("forwarder process audio message failed. ret=%d", ret);
1408 return ret; 1417 return ret;
1409 } 1418 }
@@ -1413,10 +1422,10 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1413,10 +1422,10 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1413 // cache the sequence header of aac, or first packet of mp3. 1422 // cache the sequence header of aac, or first packet of mp3.
1414 // for example, the mp3 is used for hls to write the "right" audio codec. 1423 // for example, the mp3 is used for hls to write the "right" audio codec.
1415 // TODO: FIXME: to refine the stream info system. 1424 // TODO: FIXME: to refine the stream info system.
1416 - bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg.payload, msg.size); 1425 + bool is_aac_sequence_header = SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size);
1417 if (is_aac_sequence_header || !cache_sh_audio) { 1426 if (is_aac_sequence_header || !cache_sh_audio) {
1418 srs_freep(cache_sh_audio); 1427 srs_freep(cache_sh_audio);
1419 - cache_sh_audio = msg.copy(); 1428 + cache_sh_audio = msg->copy();
1420 } 1429 }
1421 1430
1422 // cache the sequence header if aac 1431 // cache the sequence header if aac
@@ -1425,7 +1434,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1425,7 +1434,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1425 // parse detail audio codec 1434 // parse detail audio codec
1426 SrsAvcAacCodec codec; 1435 SrsAvcAacCodec codec;
1427 SrsCodecSample sample; 1436 SrsCodecSample sample;
1428 - if ((ret = codec.audio_aac_demux(msg.payload, msg.size, &sample)) != ERROR_SUCCESS) { 1437 + if ((ret = codec.audio_aac_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) {
1429 srs_error("source codec demux audio failed. ret=%d", ret); 1438 srs_error("source codec demux audio failed. ret=%d", ret);
1430 return ret; 1439 return ret;
1431 } 1440 }
@@ -1442,7 +1451,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1442,7 +1451,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1442 srs_trace("%dB audio sh, " 1451 srs_trace("%dB audio sh, "
1443 "codec(%d, profile=%s, %dchannels, %dkbps, %dHZ), " 1452 "codec(%d, profile=%s, %dchannels, %dkbps, %dHZ), "
1444 "flv(%dbits, %dchannels, %dHZ)", 1453 "flv(%dbits, %dchannels, %dHZ)",
1445 - msg.size, codec.audio_codec_id, 1454 + msg->size, codec.audio_codec_id,
1446 srs_codec_aac_object2str(codec.aac_object).c_str(), codec.aac_channels, 1455 srs_codec_aac_object2str(codec.aac_object).c_str(), codec.aac_channels,
1447 codec.audio_data_rate / 1000, aac_sample_rates[codec.aac_sample_rate], 1456 codec.audio_data_rate / 1000, aac_sample_rates[codec.aac_sample_rate],
1448 flv_sample_sizes[sample.sound_size], flv_sound_types[sample.sound_type], 1457 flv_sample_sizes[sample.sound_size], flv_sound_types[sample.sound_type],
@@ -1451,7 +1460,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1451,7 +1460,7 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1451 } 1460 }
1452 1461
1453 // cache the last gop packets 1462 // cache the last gop packets
1454 - if ((ret = gop_cache->cache(&msg)) != ERROR_SUCCESS) { 1463 + if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) {
1455 srs_error("shrink gop cache failed. ret=%d", ret); 1464 srs_error("shrink gop cache failed. ret=%d", ret);
1456 return ret; 1465 return ret;
1457 } 1466 }
@@ -1460,10 +1469,10 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio) @@ -1460,10 +1469,10 @@ int SrsSource::on_audio(SrsCommonMessage* shared_audio)
1460 // if atc, update the sequence header to abs time. 1469 // if atc, update the sequence header to abs time.
1461 if (atc) { 1470 if (atc) {
1462 if (cache_sh_audio) { 1471 if (cache_sh_audio) {
1463 - cache_sh_audio->timestamp = msg.timestamp; 1472 + cache_sh_audio->timestamp = msg->timestamp;
1464 } 1473 }
1465 if (cache_metadata) { 1474 if (cache_metadata) {
1466 - cache_metadata->timestamp = msg.timestamp; 1475 + cache_metadata->timestamp = msg->timestamp;
1467 } 1476 }
1468 } 1477 }
1469 1478
@@ -1483,8 +1492,17 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1483,8 +1492,17 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1483 } 1492 }
1484 srs_verbose("initialize shared ptr video success."); 1493 srs_verbose("initialize shared ptr video success.");
1485 1494
  1495 + srs_warn("Video dts=%"PRId64", size=%d", msg.timestamp, msg.size);
  1496 +
  1497 + return on_video_imp(&msg);
  1498 +}
  1499 +
  1500 +int SrsSource::on_video_imp(SrsSharedPtrMessage* msg)
  1501 +{
  1502 + int ret = ERROR_SUCCESS;
  1503 +
1486 #ifdef SRS_AUTO_HLS 1504 #ifdef SRS_AUTO_HLS
1487 - if ((ret = hls->on_video(&msg)) != ERROR_SUCCESS) { 1505 + if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) {
1488 // apply the error strategy for hls. 1506 // apply the error strategy for hls.
1489 // @see https://github.com/winlinvip/simple-rtmp-server/issues/264 1507 // @see https://github.com/winlinvip/simple-rtmp-server/issues/264
1490 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost); 1508 std::string hls_error_strategy = _srs_config->get_hls_on_error(_req->vhost);
@@ -1498,7 +1516,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1498,7 +1516,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1498 ret = ERROR_SUCCESS; 1516 ret = ERROR_SUCCESS;
1499 } else if (hls_error_strategy == SRS_CONF_DEFAULT_HLS_ON_ERROR_CONTINUE) { 1517 } else if (hls_error_strategy == SRS_CONF_DEFAULT_HLS_ON_ERROR_CONTINUE) {
1500 // compare the sequence header with video, continue when it's actually an sequence header. 1518 // compare the sequence header with video, continue when it's actually an sequence header.
1501 - if (ret == ERROR_HLS_DECODE_ERROR && cache_sh_video && cache_sh_video->size == msg.size) { 1519 + if (ret == ERROR_HLS_DECODE_ERROR && cache_sh_video && cache_sh_video->size == msg->size) {
1502 srs_warn("the video is actually a sequence header, ignore this packet."); 1520 srs_warn("the video is actually a sequence header, ignore this packet.");
1503 ret = ERROR_SUCCESS; 1521 ret = ERROR_SUCCESS;
1504 } else { 1522 } else {
@@ -1513,7 +1531,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1513,7 +1531,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1513 #endif 1531 #endif
1514 1532
1515 #ifdef SRS_AUTO_DVR 1533 #ifdef SRS_AUTO_DVR
1516 - if ((ret = dvr->on_video(&msg)) != ERROR_SUCCESS) { 1534 + if ((ret = dvr->on_video(msg)) != ERROR_SUCCESS) {
1517 srs_warn("dvr process video message failed, ignore and disable dvr. ret=%d", ret); 1535 srs_warn("dvr process video message failed, ignore and disable dvr. ret=%d", ret);
1518 1536
1519 // unpublish, ignore ret. 1537 // unpublish, ignore ret.
@@ -1525,7 +1543,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1525,7 +1543,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1525 #endif 1543 #endif
1526 1544
1527 #ifdef SRS_AUTO_HDS 1545 #ifdef SRS_AUTO_HDS
1528 - if ((ret = hds->on_video(&msg)) != ERROR_SUCCESS) { 1546 + if ((ret = hds->on_video(msg)) != ERROR_SUCCESS) {
1529 srs_warn("hds process video message failed, ignore and disable dvr. ret=%d", ret); 1547 srs_warn("hds process video message failed, ignore and disable dvr. ret=%d", ret);
1530 1548
1531 // unpublish, ignore ret. 1549 // unpublish, ignore ret.
@@ -1539,7 +1557,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1539,7 +1557,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1539 if (true) { 1557 if (true) {
1540 for (int i = 0; i < (int)consumers.size(); i++) { 1558 for (int i = 0; i < (int)consumers.size(); i++) {
1541 SrsConsumer* consumer = consumers.at(i); 1559 SrsConsumer* consumer = consumers.at(i);
1542 - if ((ret = consumer->enqueue(&msg, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) { 1560 + if ((ret = consumer->enqueue(msg, atc, sample_rate, frame_rate, jitter_algorithm)) != ERROR_SUCCESS) {
1543 srs_error("dispatch the video failed. ret=%d", ret); 1561 srs_error("dispatch the video failed. ret=%d", ret);
1544 return ret; 1562 return ret;
1545 } 1563 }
@@ -1552,7 +1570,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1552,7 +1570,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1552 std::vector<SrsForwarder*>::iterator it; 1570 std::vector<SrsForwarder*>::iterator it;
1553 for (it = forwarders.begin(); it != forwarders.end(); ++it) { 1571 for (it = forwarders.begin(); it != forwarders.end(); ++it) {
1554 SrsForwarder* forwarder = *it; 1572 SrsForwarder* forwarder = *it;
1555 - if ((ret = forwarder->on_video(&msg)) != ERROR_SUCCESS) { 1573 + if ((ret = forwarder->on_video(msg)) != ERROR_SUCCESS) {
1556 srs_error("forwarder process video message failed. ret=%d", ret); 1574 srs_error("forwarder process video message failed. ret=%d", ret);
1557 return ret; 1575 return ret;
1558 } 1576 }
@@ -1561,14 +1579,14 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1561,14 +1579,14 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1561 1579
1562 // cache the sequence header if h264 1580 // cache the sequence header if h264
1563 // donot cache the sequence header to gop_cache, return here. 1581 // donot cache the sequence header to gop_cache, return here.
1564 - if (SrsFlvCodec::video_is_sequence_header(msg.payload, msg.size)) { 1582 + if (SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size)) {
1565 srs_freep(cache_sh_video); 1583 srs_freep(cache_sh_video);
1566 - cache_sh_video = msg.copy(); 1584 + cache_sh_video = msg->copy();
1567 1585
1568 // parse detail audio codec 1586 // parse detail audio codec
1569 SrsAvcAacCodec codec; 1587 SrsAvcAacCodec codec;
1570 SrsCodecSample sample; 1588 SrsCodecSample sample;
1571 - if ((ret = codec.video_avc_demux(msg.payload, msg.size, &sample)) != ERROR_SUCCESS) { 1589 + if ((ret = codec.video_avc_demux(msg->payload, msg->size, &sample)) != ERROR_SUCCESS) {
1572 srs_error("source codec demux video failed. ret=%d", ret); 1590 srs_error("source codec demux video failed. ret=%d", ret);
1573 return ret; 1591 return ret;
1574 } 1592 }
@@ -1581,7 +1599,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1581,7 +1599,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1581 1599
1582 srs_trace("%dB video sh, " 1600 srs_trace("%dB video sh, "
1583 "codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %dfps, %ds)", 1601 "codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %dfps, %ds)",
1584 - msg.size, codec.video_codec_id, 1602 + msg->size, codec.video_codec_id,
1585 srs_codec_avc_profile2str(codec.avc_profile).c_str(), 1603 srs_codec_avc_profile2str(codec.avc_profile).c_str(),
1586 srs_codec_avc_level2str(codec.avc_level).c_str(), codec.width, codec.height, 1604 srs_codec_avc_level2str(codec.avc_level).c_str(), codec.width, codec.height,
1587 codec.video_data_rate / 1000, codec.frame_rate, codec.duration); 1605 codec.video_data_rate / 1000, codec.frame_rate, codec.duration);
@@ -1589,7 +1607,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1589,7 +1607,7 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1589 } 1607 }
1590 1608
1591 // cache the last gop packets 1609 // cache the last gop packets
1592 - if ((ret = gop_cache->cache(&msg)) != ERROR_SUCCESS) { 1610 + if ((ret = gop_cache->cache(msg)) != ERROR_SUCCESS) {
1593 srs_error("gop cache msg failed. ret=%d", ret); 1611 srs_error("gop cache msg failed. ret=%d", ret);
1594 return ret; 1612 return ret;
1595 } 1613 }
@@ -1598,10 +1616,10 @@ int SrsSource::on_video(SrsCommonMessage* shared_video) @@ -1598,10 +1616,10 @@ int SrsSource::on_video(SrsCommonMessage* shared_video)
1598 // if atc, update the sequence header to abs time. 1616 // if atc, update the sequence header to abs time.
1599 if (atc) { 1617 if (atc) {
1600 if (cache_sh_video) { 1618 if (cache_sh_video) {
1601 - cache_sh_video->timestamp = msg.timestamp; 1619 + cache_sh_video->timestamp = msg->timestamp;
1602 } 1620 }
1603 if (cache_metadata) { 1621 if (cache_metadata) {
1604 - cache_metadata->timestamp = msg.timestamp; 1622 + cache_metadata->timestamp = msg->timestamp;
1605 } 1623 }
1606 } 1624 }
1607 1625
@@ -495,8 +495,15 @@ public: @@ -495,8 +495,15 @@ public:
495 public: 495 public:
496 virtual bool can_publish(); 496 virtual bool can_publish();
497 virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata); 497 virtual int on_meta_data(SrsCommonMessage* msg, SrsOnMetaDataPacket* metadata);
  498 +public:
498 virtual int on_audio(SrsCommonMessage* audio); 499 virtual int on_audio(SrsCommonMessage* audio);
  500 +private:
  501 + virtual int on_audio_imp(SrsSharedPtrMessage* audio);
  502 +public:
499 virtual int on_video(SrsCommonMessage* video); 503 virtual int on_video(SrsCommonMessage* video);
  504 +private:
  505 + virtual int on_video_imp(SrsSharedPtrMessage* video);
  506 +public:
500 virtual int on_aggregate(SrsCommonMessage* msg); 507 virtual int on_aggregate(SrsCommonMessage* msg);
501 /** 508 /**
502 * the pre-publish is we are very sure we are 509 * the pre-publish is we are very sure we are
@@ -1979,6 +1979,21 @@ srs_bool srs_utils_flv_tag_is_ok(char type) @@ -1979,6 +1979,21 @@ srs_bool srs_utils_flv_tag_is_ok(char type)
1979 return type == SRS_RTMP_TYPE_AUDIO || type == SRS_RTMP_TYPE_VIDEO || type == SRS_RTMP_TYPE_SCRIPT; 1979 return type == SRS_RTMP_TYPE_AUDIO || type == SRS_RTMP_TYPE_VIDEO || type == SRS_RTMP_TYPE_SCRIPT;
1980 } 1980 }
1981 1981
  1982 +srs_bool srs_utils_flv_tag_is_audio(char type)
  1983 +{
  1984 + return type == SRS_RTMP_TYPE_AUDIO;
  1985 +}
  1986 +
  1987 +srs_bool srs_utils_flv_tag_is_video(char type)
  1988 +{
  1989 + return type == SRS_RTMP_TYPE_VIDEO;
  1990 +}
  1991 +
  1992 +srs_bool srs_utils_flv_tag_is_av(char type)
  1993 +{
  1994 + return type == SRS_RTMP_TYPE_AUDIO || type == SRS_RTMP_TYPE_VIDEO;
  1995 +}
  1996 +
1982 char srs_utils_flv_video_codec_id(char* data, int size) 1997 char srs_utils_flv_video_codec_id(char* data, int size)
1983 { 1998 {
1984 if (size < 1) { 1999 if (size < 1) {
@@ -661,6 +661,9 @@ extern int srs_utils_parse_timestamp( @@ -661,6 +661,9 @@ extern int srs_utils_parse_timestamp(
661 * @return true when tag is video/audio/script-data; otherwise, false. 661 * @return true when tag is video/audio/script-data; otherwise, false.
662 */ 662 */
663 extern srs_bool srs_utils_flv_tag_is_ok(char type); 663 extern srs_bool srs_utils_flv_tag_is_ok(char type);
  664 +extern srs_bool srs_utils_flv_tag_is_audio(char type);
  665 +extern srs_bool srs_utils_flv_tag_is_video(char type);
  666 +extern srs_bool srs_utils_flv_tag_is_av(char type);
664 667
665 /** 668 /**
666 * get the CodecID of video tag. 669 * get the CodecID of video tag.