diff --git a/trunk/configure b/trunk/configure
index ddfe19b7b..f9c1b42b4 100755
--- a/trunk/configure
+++ b/trunk/configure
@@ -251,7 +251,7 @@ MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_buffer"
"srs_kernel_utility" "srs_kernel_flv" "srs_kernel_codec" "srs_kernel_io"
"srs_kernel_consts" "srs_kernel_aac" "srs_kernel_mp3" "srs_kernel_ts" "srs_kernel_ps"
"srs_kernel_stream" "srs_kernel_balance" "srs_kernel_mp4" "srs_kernel_file"
- "srs_kernel_kbps" "srs_kernel_rtc_rtp" "srs_kernel_rtc_rtcp")
+ "srs_kernel_kbps" "srs_kernel_rtc_rtp" "srs_kernel_rtc_rtcp" "srs_kernel_packet")
KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . $SRS_WORKDIR/auto/modules.sh
KERNEL_OBJS="${MODULE_OBJS[@]}"
#
diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md
index 20551f544..f0d1e5324 100644
--- a/trunk/doc/CHANGELOG.md
+++ b/trunk/doc/CHANGELOG.md
@@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 7.0 Changelog
+* v7.0, 2025-09-01, Merge [#4465](https://github.com/ossrs/srs/pull/4465): AI: Replace SrsSharedPtrMessage with SrsMediaPacket for unified media packet handling. v7.0.74 (#4465)
* v7.0, 2025-09-01, Merge [#4464](https://github.com/ossrs/srs/pull/4464): AI: Use shared ptr in RTMP message. v7.0.73 (#4464)
* v7.0, 2025-09-01, Merge [#4463](https://github.com/ossrs/srs/pull/4463): AI: Use SrsHttpUri for URL parsing and add legacy RTMP URL conversion. v7.0.72 (#4463)
* v7.0, 2025-09-01, Merge [#4462](https://github.com/ossrs/srs/pull/4462): HTTP: Rename HTTP hijack to dynamic match for better clarity. v7.0.71 (#4462)
diff --git a/trunk/src/app/srs_app_caster_flv.cpp b/trunk/src/app/srs_app_caster_flv.cpp
index e479e5735..1b7d5b5fe 100644
--- a/trunk/src/app/srs_app_caster_flv.cpp
+++ b/trunk/src/app/srs_app_caster_flv.cpp
@@ -279,11 +279,15 @@ srs_error_t SrsDynamicHttpConn::do_proxy(ISrsHttpResponseReader *rr, SrsFlvDecod
return srs_error_wrap(err, "read tag data");
}
- SrsSharedPtrMessage *msg = NULL;
- if ((err = srs_rtmp_create_msg(type, time, data, size, sdk->sid(), &msg)) != srs_success) {
+ SrsCommonMessage *cmsg = NULL;
+ if ((err = srs_rtmp_create_msg(type, time, data, size, sdk->sid(), &cmsg)) != srs_success) {
return srs_error_wrap(err, "create message");
}
+ SrsMediaPacket *msg = new SrsMediaPacket();
+ cmsg->to_msg(msg);
+ srs_freep(cmsg);
+
// TODO: FIXME: for post flv, reconnect when error.
if ((err = sdk->send_and_free_message(msg)) != srs_success) {
return srs_error_wrap(err, "send message");
diff --git a/trunk/src/app/srs_app_dash.cpp b/trunk/src/app/srs_app_dash.cpp
index 1aaab172f..3cec13ada 100644
--- a/trunk/src/app/srs_app_dash.cpp
+++ b/trunk/src/app/srs_app_dash.cpp
@@ -112,7 +112,7 @@ srs_error_t SrsFragmentedMp4::initialize(ISrsRequest *r, bool video, int64_t tim
return err;
}
-srs_error_t SrsFragmentedMp4::write(SrsSharedPtrMessage *shared_msg, SrsFormat *format)
+srs_error_t SrsFragmentedMp4::write(SrsMediaPacket *shared_msg, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -480,7 +480,7 @@ void SrsDashController::on_unpublish()
}
}
-srs_error_t SrsDashController::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsDashController::on_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -552,7 +552,7 @@ srs_error_t SrsDashController::on_audio(SrsSharedPtrMessage *shared_audio, SrsFo
return err;
}
-srs_error_t SrsDashController::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsDashController::on_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -641,7 +641,7 @@ srs_error_t SrsDashController::refresh_mpd(SrsFormat *format)
return err;
}
-srs_error_t SrsDashController::refresh_init_mp4(SrsSharedPtrMessage *msg, SrsFormat *format)
+srs_error_t SrsDashController::refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -796,7 +796,7 @@ srs_error_t SrsDash::on_publish()
return err;
}
-srs_error_t SrsDash::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsDash::on_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -818,7 +818,7 @@ srs_error_t SrsDash::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *form
return err;
}
-srs_error_t SrsDash::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsDash::on_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_dash.hpp b/trunk/src/app/srs_app_dash.hpp
index 4bcdecfe9..8b6e570b1 100644
--- a/trunk/src/app/srs_app_dash.hpp
+++ b/trunk/src/app/srs_app_dash.hpp
@@ -16,7 +16,7 @@
class ISrsRequest;
class SrsOriginHub;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsFormat;
class SrsFileWriter;
class SrsMpdWriter;
@@ -54,7 +54,7 @@ public:
// Initialize the fragment, create the home dir, open the file.
virtual srs_error_t initialize(ISrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid);
// Write media message to fragment.
- virtual srs_error_t write(SrsSharedPtrMessage *shared_msg, SrsFormat *format);
+ virtual srs_error_t write(SrsMediaPacket *shared_msg, SrsFormat *format);
// Reap the fragment, close the fd and rename tmp to official file.
virtual srs_error_t reap(uint64_t &dts);
};
@@ -154,12 +154,12 @@ public:
virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
private:
virtual srs_error_t refresh_mpd(SrsFormat *format);
- virtual srs_error_t refresh_init_mp4(SrsSharedPtrMessage *msg, SrsFormat *format);
+ virtual srs_error_t refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *format);
};
// The MPEG-DASH encoder, transmux RTMP to DASH.
@@ -190,9 +190,9 @@ public:
// When stream start publishing.
virtual srs_error_t on_publish();
// When got an shared audio message.
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
// When got an shared video message.
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
// When stream stop publishing.
virtual void on_unpublish();
};
diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp
index db5b994b5..c0f36c5b3 100644
--- a/trunk/src/app/srs_app_dvr.cpp
+++ b/trunk/src/app/srs_app_dvr.cpp
@@ -117,17 +117,17 @@ srs_error_t SrsDvrSegmenter::open()
return err;
}
-srs_error_t SrsDvrSegmenter::write_metadata(SrsSharedPtrMessage *metadata)
+srs_error_t SrsDvrSegmenter::write_metadata(SrsMediaPacket *metadata)
{
return encode_metadata(metadata);
}
-srs_error_t SrsDvrSegmenter::write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsDvrSegmenter::write_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
// TODO: FIXME: Use SrsSharedPtr instead.
- SrsUniquePtr audio(shared_audio->copy());
+ SrsUniquePtr audio(shared_audio->copy());
if ((err = jitter->correct(audio.get(), jitter_algorithm)) != srs_success) {
return srs_error_wrap(err, "jitter");
@@ -144,12 +144,12 @@ srs_error_t SrsDvrSegmenter::write_audio(SrsSharedPtrMessage *shared_audio, SrsF
return err;
}
-srs_error_t SrsDvrSegmenter::write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsDvrSegmenter::write_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
// TODO: FIXME: Use SrsSharedPtr instead.
- SrsUniquePtr video(shared_video->copy());
+ SrsUniquePtr video(shared_video->copy());
if ((err = jitter->correct(video.get(), jitter_algorithm)) != srs_success) {
return srs_error_wrap(err, "jitter");
@@ -215,7 +215,7 @@ string SrsDvrSegmenter::generate_path()
return flv_path;
}
-srs_error_t SrsDvrSegmenter::on_update_duration(SrsSharedPtrMessage *msg)
+srs_error_t SrsDvrSegmenter::on_update_duration(SrsMediaPacket *msg)
{
fragment->append(msg->timestamp);
return srs_success;
@@ -310,7 +310,7 @@ srs_error_t SrsDvrFlvSegmenter::open_encoder()
return err;
}
-srs_error_t SrsDvrFlvSegmenter::encode_metadata(SrsSharedPtrMessage *metadata)
+srs_error_t SrsDvrFlvSegmenter::encode_metadata(SrsMediaPacket *metadata)
{
srs_error_t err = srs_success;
@@ -366,7 +366,7 @@ srs_error_t SrsDvrFlvSegmenter::encode_metadata(SrsSharedPtrMessage *metadata)
return err;
}
-srs_error_t SrsDvrFlvSegmenter::encode_audio(SrsSharedPtrMessage *audio, SrsFormat *format)
+srs_error_t SrsDvrFlvSegmenter::encode_audio(SrsMediaPacket *audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -379,7 +379,7 @@ srs_error_t SrsDvrFlvSegmenter::encode_audio(SrsSharedPtrMessage *audio, SrsForm
return err;
}
-srs_error_t SrsDvrFlvSegmenter::encode_video(SrsSharedPtrMessage *video, SrsFormat *format)
+srs_error_t SrsDvrFlvSegmenter::encode_video(SrsMediaPacket *video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -439,12 +439,12 @@ srs_error_t SrsDvrMp4Segmenter::open_encoder()
return err;
}
-srs_error_t SrsDvrMp4Segmenter::encode_metadata(SrsSharedPtrMessage * /*metadata*/)
+srs_error_t SrsDvrMp4Segmenter::encode_metadata(SrsMediaPacket * /*metadata*/)
{
return srs_success;
}
-srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage *audio, SrsFormat *format)
+srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsMediaPacket *audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -472,7 +472,7 @@ srs_error_t SrsDvrMp4Segmenter::encode_audio(SrsSharedPtrMessage *audio, SrsForm
return err;
}
-srs_error_t SrsDvrMp4Segmenter::encode_video(SrsSharedPtrMessage *video, SrsFormat *format)
+srs_error_t SrsDvrMp4Segmenter::encode_video(SrsMediaPacket *video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -607,7 +607,7 @@ void SrsDvrPlan::on_unpublish()
{
}
-srs_error_t SrsDvrPlan::on_meta_data(SrsSharedPtrMessage *shared_metadata)
+srs_error_t SrsDvrPlan::on_meta_data(SrsMediaPacket *shared_metadata)
{
srs_error_t err = srs_success;
@@ -618,7 +618,7 @@ srs_error_t SrsDvrPlan::on_meta_data(SrsSharedPtrMessage *shared_metadata)
return segment->write_metadata(shared_metadata);
}
-srs_error_t SrsDvrPlan::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsDvrPlan::on_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -633,7 +633,7 @@ srs_error_t SrsDvrPlan::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *f
return err;
}
-srs_error_t SrsDvrPlan::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsDvrPlan::on_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -816,7 +816,7 @@ void SrsDvrSegmentPlan::on_unpublish()
SrsDvrPlan::on_unpublish();
}
-srs_error_t SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsDvrSegmentPlan::on_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -831,7 +831,7 @@ srs_error_t SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage *shared_audio, SrsFo
return err;
}
-srs_error_t SrsDvrSegmentPlan::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsDvrSegmentPlan::on_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -846,7 +846,7 @@ srs_error_t SrsDvrSegmentPlan::on_video(SrsSharedPtrMessage *shared_video, SrsFo
return err;
}
-srs_error_t SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage *msg)
+srs_error_t SrsDvrSegmentPlan::update_duration(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -981,7 +981,7 @@ void SrsDvr::on_unpublish()
plan->on_unpublish();
}
-srs_error_t SrsDvr::on_meta_data(SrsSharedPtrMessage *metadata)
+srs_error_t SrsDvr::on_meta_data(SrsMediaPacket *metadata)
{
srs_error_t err = srs_success;
@@ -997,7 +997,7 @@ srs_error_t SrsDvr::on_meta_data(SrsSharedPtrMessage *metadata)
return err;
}
-srs_error_t SrsDvr::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsDvr::on_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
// the dvr for this stream is not actived.
if (!actived) {
@@ -1007,7 +1007,7 @@ srs_error_t SrsDvr::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *forma
return plan->on_audio(shared_audio, format);
}
-srs_error_t SrsDvr::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsDvr::on_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
// the dvr for this stream is not actived.
if (!actived) {
diff --git a/trunk/src/app/srs_app_dvr.hpp b/trunk/src/app/srs_app_dvr.hpp
index 60982b503..8df9cdbb0 100644
--- a/trunk/src/app/srs_app_dvr.hpp
+++ b/trunk/src/app/srs_app_dvr.hpp
@@ -17,7 +17,7 @@ class SrsOriginHub;
class ISrsRequest;
class SrsBuffer;
class SrsRtmpJitter;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsFileWriter;
class SrsFlvTransmuxer;
class SrsDvrPlan;
@@ -65,13 +65,13 @@ public:
// @remark Ignore when file is already open.
virtual srs_error_t open();
// Write the metadata.
- virtual srs_error_t write_metadata(SrsSharedPtrMessage *metadata);
+ virtual srs_error_t write_metadata(SrsMediaPacket *metadata);
// Write audio packet.
// @param shared_audio, directly ptr, copy it if need to save it.
- virtual srs_error_t write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
+ virtual srs_error_t write_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
// Write video packet.
// @param shared_video, directly ptr, copy it if need to save it.
- virtual srs_error_t write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format);
// Refresh the metadata. For example, there is duration in flv metadata,
// when DVR in append mode, the duration must be update every some seconds.
// @remark Maybe ignored by concreate segmenter.
@@ -82,16 +82,16 @@ public:
protected:
virtual srs_error_t open_encoder() = 0;
- virtual srs_error_t encode_metadata(SrsSharedPtrMessage *metadata) = 0;
- virtual srs_error_t encode_audio(SrsSharedPtrMessage *audio, SrsFormat *format) = 0;
- virtual srs_error_t encode_video(SrsSharedPtrMessage *video, SrsFormat *format) = 0;
+ virtual srs_error_t encode_metadata(SrsMediaPacket *metadata) = 0;
+ virtual srs_error_t encode_audio(SrsMediaPacket *audio, SrsFormat *format) = 0;
+ virtual srs_error_t encode_video(SrsMediaPacket *video, SrsFormat *format) = 0;
virtual srs_error_t close_encoder() = 0;
private:
// Generate the flv segment path.
virtual std::string generate_path();
// When update the duration of segment by rtmp msg.
- virtual srs_error_t on_update_duration(SrsSharedPtrMessage *msg);
+ virtual srs_error_t on_update_duration(SrsMediaPacket *msg);
};
// The FLV segmenter to use FLV encoder to write file.
@@ -120,9 +120,9 @@ public:
protected:
virtual srs_error_t open_encoder();
- virtual srs_error_t encode_metadata(SrsSharedPtrMessage *metadata);
- virtual srs_error_t encode_audio(SrsSharedPtrMessage *audio, SrsFormat *format);
- virtual srs_error_t encode_video(SrsSharedPtrMessage *video, SrsFormat *format);
+ virtual srs_error_t encode_metadata(SrsMediaPacket *metadata);
+ virtual srs_error_t encode_audio(SrsMediaPacket *audio, SrsFormat *format);
+ virtual srs_error_t encode_video(SrsMediaPacket *video, SrsFormat *format);
virtual srs_error_t close_encoder();
};
@@ -142,9 +142,9 @@ public:
protected:
virtual srs_error_t open_encoder();
- virtual srs_error_t encode_metadata(SrsSharedPtrMessage *metadata);
- virtual srs_error_t encode_audio(SrsSharedPtrMessage *audio, SrsFormat *format);
- virtual srs_error_t encode_video(SrsSharedPtrMessage *video, SrsFormat *format);
+ virtual srs_error_t encode_metadata(SrsMediaPacket *metadata);
+ virtual srs_error_t encode_audio(SrsMediaPacket *audio, SrsFormat *format);
+ virtual srs_error_t encode_video(SrsMediaPacket *video, SrsFormat *format);
virtual srs_error_t close_encoder();
};
@@ -184,9 +184,9 @@ public:
virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r);
virtual srs_error_t on_publish(ISrsRequest *r);
virtual void on_unpublish();
- virtual srs_error_t on_meta_data(SrsSharedPtrMessage *shared_metadata);
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
// Internal interface for segmenter.
public:
// When segmenter close a segment.
@@ -226,11 +226,11 @@ public:
virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r);
virtual srs_error_t on_publish(ISrsRequest *r);
virtual void on_unpublish();
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
private:
- virtual srs_error_t update_duration(SrsSharedPtrMessage *msg);
+ virtual srs_error_t update_duration(SrsMediaPacket *msg);
};
// DVR(Digital Video Recorder) to record RTMP stream to flv/mp4 file.
@@ -264,13 +264,13 @@ public:
// when encoder stop(unpublish) to publish RTMP stream.
virtual void on_unpublish();
// get some information from metadata, it's optinal.
- virtual srs_error_t on_meta_data(SrsSharedPtrMessage *metadata);
+ virtual srs_error_t on_meta_data(SrsMediaPacket *metadata);
// mux the audio packets to dvr.
// @param shared_audio, directly ptr, copy it if need to save it.
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *foramt);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *foramt);
// mux the video packets to dvr.
// @param shared_video, directly ptr, copy it if need to save it.
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
};
extern SrsAsyncCallWorker *_srs_dvr_async;
diff --git a/trunk/src/app/srs_app_edge.cpp b/trunk/src/app/srs_app_edge.cpp
index b17585eab..a426bb8ff 100644
--- a/trunk/src/app/srs_app_edge.cpp
+++ b/trunk/src/app/srs_app_edge.cpp
@@ -130,7 +130,7 @@ srs_error_t SrsEdgeRtmpUpstream::recv_message(SrsCommonMessage **pmsg)
return sdk->recv_message(pmsg);
}
-srs_error_t SrsEdgeRtmpUpstream::decode_message(SrsCommonMessage *msg, SrsPacket **ppacket)
+srs_error_t SrsEdgeRtmpUpstream::decode_message(SrsCommonMessage *msg, SrsRtmpCommand **ppacket)
{
return sdk->decode_message(msg, ppacket);
}
@@ -333,11 +333,11 @@ srs_error_t SrsEdgeFlvUpstream::recv_message(SrsCommonMessage **pmsg)
return err;
}
-srs_error_t SrsEdgeFlvUpstream::decode_message(SrsCommonMessage *msg, SrsPacket **ppacket)
+srs_error_t SrsEdgeFlvUpstream::decode_message(SrsCommonMessage *msg, SrsRtmpCommand **ppacket)
{
srs_error_t err = srs_success;
- SrsPacket *packet = NULL;
+ SrsRtmpCommand *packet = NULL;
SrsBuffer stream(msg->payload(), msg->size());
SrsMessageHeader &header = msg->header;
@@ -647,11 +647,11 @@ srs_error_t SrsEdgeIngester::process_publish_message(SrsCommonMessage *msg, stri
// process onMetaData
if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
- SrsPacket *pkt_raw = NULL;
+ SrsRtmpCommand *pkt_raw = NULL;
if ((err = upstream->decode_message(msg, &pkt_raw)) != srs_success) {
return srs_error_wrap(err, "decode message");
}
- SrsUniquePtr pkt(pkt_raw);
+ SrsUniquePtr pkt(pkt_raw);
if (dynamic_cast(pkt.get())) {
SrsOnMetaDataPacket *metadata = dynamic_cast(pkt.get());
@@ -666,11 +666,11 @@ srs_error_t SrsEdgeIngester::process_publish_message(SrsCommonMessage *msg, stri
// call messages, for example, reject, redirect.
if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {
- SrsPacket *pkt_raw = NULL;
+ SrsRtmpCommand *pkt_raw = NULL;
if ((err = upstream->decode_message(msg, &pkt_raw)) != srs_success) {
return srs_error_wrap(err, "decode message");
}
- SrsUniquePtr pkt(pkt_raw);
+ SrsUniquePtr pkt(pkt_raw);
// RTMP 302 redirect
if (dynamic_cast(pkt.get())) {
@@ -928,10 +928,8 @@ srs_error_t SrsEdgeForwarder::proxy(SrsCommonMessage *msg)
return err;
}
- SrsSharedPtrMessage copy;
- if ((err = copy.create(msg)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket copy;
+ msg->to_msg(©);
copy.stream_id = sdk->sid();
if ((err = queue->enqueue(copy.copy())) != srs_success) {
diff --git a/trunk/src/app/srs_app_edge.hpp b/trunk/src/app/srs_app_edge.hpp
index e823aa654..4ed00b719 100644
--- a/trunk/src/app/srs_app_edge.hpp
+++ b/trunk/src/app/srs_app_edge.hpp
@@ -28,7 +28,7 @@ class SrsKbps;
class SrsLbRoundRobin;
class SrsTcpClient;
class SrsSimpleRtmpClient;
-class SrsPacket;
+class SrsRtmpCommand;
class SrsHttpClient;
class ISrsHttpMessage;
class SrsHttpFileReader;
@@ -66,7 +66,7 @@ public:
public:
virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb) = 0;
virtual srs_error_t recv_message(SrsCommonMessage **pmsg) = 0;
- virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsPacket **ppacket) = 0;
+ virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsRtmpCommand **ppacket) = 0;
virtual void close() = 0;
public:
@@ -96,7 +96,7 @@ public:
public:
virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb);
virtual srs_error_t recv_message(SrsCommonMessage **pmsg);
- virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsPacket **ppacket);
+ virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsRtmpCommand **ppacket);
virtual void close();
public:
@@ -135,7 +135,7 @@ private:
public:
virtual srs_error_t recv_message(SrsCommonMessage **pmsg);
- virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsPacket **ppacket);
+ virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsRtmpCommand **ppacket);
virtual void close();
public:
diff --git a/trunk/src/app/srs_app_forward.cpp b/trunk/src/app/srs_app_forward.cpp
index 6e50df3aa..e9d9d664d 100644
--- a/trunk/src/app/srs_app_forward.cpp
+++ b/trunk/src/app/srs_app_forward.cpp
@@ -98,11 +98,11 @@ void SrsForwarder::on_unpublish()
sdk->close();
}
-srs_error_t SrsForwarder::on_meta_data(SrsSharedPtrMessage *shared_metadata)
+srs_error_t SrsForwarder::on_meta_data(SrsMediaPacket *shared_metadata)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *metadata = shared_metadata->copy();
+ SrsMediaPacket *metadata = shared_metadata->copy();
// TODO: FIXME: config the jitter of Forwarder.
if ((err = jitter->correct(metadata, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
@@ -116,11 +116,11 @@ srs_error_t SrsForwarder::on_meta_data(SrsSharedPtrMessage *shared_metadata)
return err;
}
-srs_error_t SrsForwarder::on_audio(SrsSharedPtrMessage *shared_audio)
+srs_error_t SrsForwarder::on_audio(SrsMediaPacket *shared_audio)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *msg = shared_audio->copy();
+ SrsMediaPacket *msg = shared_audio->copy();
// TODO: FIXME: config the jitter of Forwarder.
if ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
@@ -139,11 +139,11 @@ srs_error_t SrsForwarder::on_audio(SrsSharedPtrMessage *shared_audio)
return err;
}
-srs_error_t SrsForwarder::on_video(SrsSharedPtrMessage *shared_video)
+srs_error_t SrsForwarder::on_video(SrsMediaPacket *shared_video)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *msg = shared_video->copy();
+ SrsMediaPacket *msg = shared_video->copy();
// TODO: FIXME: config the jitter of Forwarder.
if ((err = jitter->correct(msg, SrsRtmpJitterAlgorithmOFF)) != srs_success) {
diff --git a/trunk/src/app/srs_app_forward.hpp b/trunk/src/app/srs_app_forward.hpp
index 2dce9a1db..b77968aef 100644
--- a/trunk/src/app/srs_app_forward.hpp
+++ b/trunk/src/app/srs_app_forward.hpp
@@ -14,7 +14,7 @@
#include
class ISrsProtocolReadWriter;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsOnMetaDataPacket;
class SrsMessageQueue;
class SrsRtmpJitter;
@@ -46,8 +46,8 @@ private:
SrsRtmpJitter *jitter;
SrsMessageQueue *queue;
// Cache the sequence header for retry when slave is failed.
- SrsSharedPtrMessage *sh_audio;
- SrsSharedPtrMessage *sh_video;
+ SrsMediaPacket *sh_audio;
+ SrsMediaPacket *sh_video;
public:
SrsForwarder(SrsOriginHub *h);
@@ -62,13 +62,13 @@ public:
virtual void on_unpublish();
// Forward the audio packet.
// @param shared_metadata, directly ptr, copy it if need to save it.
- virtual srs_error_t on_meta_data(SrsSharedPtrMessage *shared_metadata);
+ virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata);
// Forward the audio packet.
// @param shared_audio, directly ptr, copy it if need to save it.
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio);
// Forward the video packet.
// @param shared_video, directly ptr, copy it if need to save it.
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video);
// Interface ISrsReusableThread2Handler.
public:
virtual srs_error_t cycle();
diff --git a/trunk/src/app/srs_app_gb28181.cpp b/trunk/src/app/srs_app_gb28181.cpp
index 18d4a7df2..6bb9a340f 100644
--- a/trunk/src/app/srs_app_gb28181.cpp
+++ b/trunk/src/app/srs_app_gb28181.cpp
@@ -1547,15 +1547,15 @@ SrsMpegpsQueue::SrsMpegpsQueue()
SrsMpegpsQueue::~SrsMpegpsQueue()
{
- std::map::iterator it;
+ std::map::iterator it;
for (it = msgs.begin(); it != msgs.end(); ++it) {
- SrsSharedPtrMessage *msg = it->second;
+ SrsMediaPacket *msg = it->second;
srs_freep(msg);
}
msgs.clear();
}
-srs_error_t SrsMpegpsQueue::push(SrsSharedPtrMessage *msg)
+srs_error_t SrsMpegpsQueue::push(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -1588,7 +1588,7 @@ srs_error_t SrsMpegpsQueue::push(SrsSharedPtrMessage *msg)
return err;
}
-SrsSharedPtrMessage *SrsMpegpsQueue::dequeue()
+SrsMediaPacket *SrsMpegpsQueue::dequeue()
{
// got 2+ videos and audios, ok to dequeue.
bool av_ok = nb_videos >= 2 && nb_audios >= 2;
@@ -1596,8 +1596,8 @@ SrsSharedPtrMessage *SrsMpegpsQueue::dequeue()
bool av_overflow = nb_videos > 100 || nb_audios > 300;
if (av_ok || av_overflow) {
- std::map::iterator it = msgs.begin();
- SrsSharedPtrMessage *msg = it->second;
+ std::map::iterator it = msgs.begin();
+ SrsMediaPacket *msg = it->second;
msgs.erase(it);
if (msg->is_audio()) {
@@ -2107,12 +2107,14 @@ srs_error_t SrsGbMuxer::rtmp_write_packet(char type, uint32_t timestamp, char *d
return srs_error_wrap(err, "connect");
}
- SrsSharedPtrMessage *msg = NULL;
-
- if ((err = srs_rtmp_create_msg(type, timestamp, data, size, sdk_->sid(), &msg)) != srs_success) {
+ SrsCommonMessage *cmsg = NULL;
+ if ((err = srs_rtmp_create_msg(type, timestamp, data, size, sdk_->sid(), &cmsg)) != srs_success) {
return srs_error_wrap(err, "create message");
}
- srs_assert(msg);
+
+ SrsMediaPacket *msg = new SrsMediaPacket();
+ cmsg->to_msg(msg);
+ srs_freep(cmsg);
// push msg to queue.
if ((err = queue_->push(msg)) != srs_success) {
diff --git a/trunk/src/app/srs_app_gb28181.hpp b/trunk/src/app/srs_app_gb28181.hpp
index 2b1ebbe99..77e3d9bf0 100644
--- a/trunk/src/app/srs_app_gb28181.hpp
+++ b/trunk/src/app/srs_app_gb28181.hpp
@@ -37,7 +37,7 @@ class SrsSimpleRtmpClient;
struct SrsRawAacStreamCodec;
class SrsRawH264Stream;
class SrsRawHEVCStream;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsPithyPrint;
class SrsRawAacStream;
class ISrsHttpServeMux;
@@ -485,7 +485,7 @@ class SrsMpegpsQueue
{
private:
// The key: dts, value: msg.
- std::map msgs;
+ std::map msgs;
int nb_audios;
int nb_videos;
@@ -494,8 +494,8 @@ public:
virtual ~SrsMpegpsQueue();
public:
- virtual srs_error_t push(SrsSharedPtrMessage *msg);
- virtual SrsSharedPtrMessage *dequeue();
+ virtual srs_error_t push(SrsMediaPacket *msg);
+ virtual SrsMediaPacket *dequeue();
};
// Mux GB28181 to RTMP.
diff --git a/trunk/src/app/srs_app_hds.cpp b/trunk/src/app/srs_app_hds.cpp
index 378c8a2b3..ac2ba9bb5 100644
--- a/trunk/src/app/srs_app_hds.cpp
+++ b/trunk/src/app/srs_app_hds.cpp
@@ -38,7 +38,7 @@ char flv_header[] = {'F', 'L', 'V',
0x01, 0x05, 0x00, 0x00, 0x00, 0x09,
0x00, 0x00, 0x00, 0x00};
-string serialFlv(SrsSharedPtrMessage *msg)
+string serialFlv(SrsMediaPacket *msg)
{
int size = 15 + msg->size();
char *byte = new char[size];
@@ -81,22 +81,22 @@ public:
srs_freep(audioSh);
// clean msgs
- list::iterator iter;
+ list::iterator iter;
for (iter = msgs.begin(); iter != msgs.end(); ++iter) {
- SrsSharedPtrMessage *msg = *iter;
+ SrsMediaPacket *msg = *iter;
srs_freep(msg);
}
}
- void on_video(SrsSharedPtrMessage *msg)
+ void on_video(SrsMediaPacket *msg)
{
- SrsSharedPtrMessage *_msg = msg->copy();
+ SrsMediaPacket *_msg = msg->copy();
msgs.push_back(_msg);
}
- void on_audio(SrsSharedPtrMessage *msg)
+ void on_audio(SrsMediaPacket *msg)
{
- SrsSharedPtrMessage *_msg = msg->copy();
+ SrsMediaPacket *_msg = msg->copy();
msgs.push_back(_msg);
}
@@ -116,9 +116,9 @@ public:
data.append(serialFlv(audioSh));
}
- list::iterator iter;
+ list::iterator iter;
for (iter = msgs.begin(); iter != msgs.end(); ++iter) {
- SrsSharedPtrMessage *msg = *iter;
+ SrsMediaPacket *msg = *iter;
data.append(serialFlv(msg));
}
@@ -158,10 +158,10 @@ public:
long long last_msg_ts = 0;
if (msgs.size() >= 2) {
- SrsSharedPtrMessage *first_msg = msgs.front();
+ SrsMediaPacket *first_msg = msgs.front();
first_msg_ts = first_msg->timestamp;
- SrsSharedPtrMessage *last_msg = msgs.back();
+ SrsMediaPacket *last_msg = msgs.back();
last_msg_ts = last_msg->timestamp;
duration_ms = (int)(last_msg_ts - first_msg_ts);
@@ -200,13 +200,13 @@ public:
return start_time;
}
- void set_video_sh(SrsSharedPtrMessage *msg)
+ void set_video_sh(SrsMediaPacket *msg)
{
srs_freep(videoSh);
videoSh = msg->copy();
}
- void set_audio_sh(SrsSharedPtrMessage *msg)
+ void set_audio_sh(SrsMediaPacket *msg)
{
srs_freep(audioSh);
audioSh = msg->copy();
@@ -219,7 +219,7 @@ public:
private:
ISrsRequest *req;
- list msgs;
+ list msgs;
/*!
the index of this fragment
@@ -227,8 +227,8 @@ private:
int index;
long long start_time;
- SrsSharedPtrMessage *videoSh;
- SrsSharedPtrMessage *audioSh;
+ SrsMediaPacket *videoSh;
+ SrsMediaPacket *audioSh;
string path;
};
@@ -290,7 +290,7 @@ srs_error_t SrsHds::on_unpublish()
return err;
}
-srs_error_t SrsHds::on_video(SrsSharedPtrMessage *msg)
+srs_error_t SrsHds::on_video(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -340,7 +340,7 @@ srs_error_t SrsHds::on_video(SrsSharedPtrMessage *msg)
return err;
}
-srs_error_t SrsHds::on_audio(SrsSharedPtrMessage *msg)
+srs_error_t SrsHds::on_audio(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_hds.hpp b/trunk/src/app/srs_app_hds.hpp
index f7037bee9..6ae7b1959 100644
--- a/trunk/src/app/srs_app_hds.hpp
+++ b/trunk/src/app/srs_app_hds.hpp
@@ -14,7 +14,7 @@
#include
class ISrsRequest;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsHdsFragment;
class SrsLiveSource;
@@ -28,8 +28,8 @@ public:
srs_error_t on_publish(ISrsRequest *req);
srs_error_t on_unpublish();
- srs_error_t on_video(SrsSharedPtrMessage *msg);
- srs_error_t on_audio(SrsSharedPtrMessage *msg);
+ srs_error_t on_video(SrsMediaPacket *msg);
+ srs_error_t on_audio(SrsMediaPacket *msg);
private:
srs_error_t flush_mainfest();
@@ -40,8 +40,8 @@ private:
std::list fragments;
SrsHdsFragment *currentSegment;
int fragment_index;
- SrsSharedPtrMessage *video_sh;
- SrsSharedPtrMessage *audio_sh;
+ SrsMediaPacket *video_sh;
+ SrsMediaPacket *audio_sh;
ISrsRequest *hds_req;
bool hds_enabled;
diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp
index e48dc7887..33b552f75 100644
--- a/trunk/src/app/srs_app_hls.cpp
+++ b/trunk/src/app/srs_app_hls.cpp
@@ -203,7 +203,7 @@ void SrsHlsM4sSegment::config_cipher(unsigned char *key, unsigned char *iv)
memcpy(this->iv, iv, 16);
}
-srs_error_t SrsHlsM4sSegment::write(SrsSharedPtrMessage *shared_msg, SrsFormat *format)
+srs_error_t SrsHlsM4sSegment::write(SrsMediaPacket *shared_msg, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -580,7 +580,7 @@ srs_error_t SrsHlsFmp4Muxer::write_init_mp4(SrsFormat *format, bool has_video, b
return err;
}
-srs_error_t SrsHlsFmp4Muxer::write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsHlsFmp4Muxer::write_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -604,7 +604,7 @@ srs_error_t SrsHlsFmp4Muxer::write_audio(SrsSharedPtrMessage *shared_audio, SrsF
return err;
}
-srs_error_t SrsHlsFmp4Muxer::write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsHlsFmp4Muxer::write_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -2039,7 +2039,7 @@ srs_error_t SrsHlsController::on_unpublish()
return err;
}
-srs_error_t SrsHlsController::on_sequence_header(SrsSharedPtrMessage *msg, SrsFormat *format)
+srs_error_t SrsHlsController::on_sequence_header(SrsMediaPacket *msg, SrsFormat *format)
{
// TODO: support discontinuity for the same stream
// currently we reap and insert discontinity when encoder republish,
@@ -2050,10 +2050,10 @@ srs_error_t SrsHlsController::on_sequence_header(SrsSharedPtrMessage *msg, SrsFo
return muxer->on_sequence_header();
}
-srs_error_t SrsHlsController::write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsHlsController::write_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
- SrsAudioFrame *frame = format->audio;
+ SrsParsedAudioPacket *frame = format->audio;
// Reset the aac samples counter when DTS jitter.
if (previous_audio_dts > shared_audio->timestamp) {
@@ -2140,10 +2140,10 @@ srs_error_t SrsHlsController::write_audio(SrsSharedPtrMessage *shared_audio, Srs
return err;
}
-srs_error_t SrsHlsController::write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsHlsController::write_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
- SrsVideoFrame *frame = format->video;
+ SrsParsedVideoPacket *frame = format->video;
int64_t dts = shared_video->timestamp * 90;
// Refresh the codec ASAP.
@@ -2306,10 +2306,10 @@ srs_error_t SrsHlsMp4Controller::on_unpublish()
return err;
}
-srs_error_t SrsHlsMp4Controller::write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsHlsMp4Controller::write_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
- SrsAudioFrame *frame = format->audio;
+ SrsParsedAudioPacket *frame = format->audio;
// Ignore audio sequence header
if (format->is_aac_sequence_header() || format->is_mp3_sequence_header()) {
@@ -2332,10 +2332,10 @@ srs_error_t SrsHlsMp4Controller::write_audio(SrsSharedPtrMessage *shared_audio,
return err;
}
-srs_error_t SrsHlsMp4Controller::write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsHlsMp4Controller::write_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
- SrsVideoFrame *frame = format->video;
+ SrsParsedVideoPacket *frame = format->video;
// Refresh the codec ASAP.
if (muxer_->latest_vcodec() != frame->vcodec()->id) {
@@ -2353,7 +2353,7 @@ srs_error_t SrsHlsMp4Controller::write_video(SrsSharedPtrMessage *shared_video,
return err;
}
-srs_error_t SrsHlsMp4Controller::on_sequence_header(SrsSharedPtrMessage *msg, SrsFormat *format)
+srs_error_t SrsHlsMp4Controller::on_sequence_header(SrsMediaPacket *msg, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -2622,7 +2622,7 @@ void SrsHls::on_unpublish()
unpublishing_ = false;
}
-srs_error_t SrsHls::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format)
+srs_error_t SrsHls::on_audio(SrsMediaPacket *shared_audio, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -2642,7 +2642,7 @@ srs_error_t SrsHls::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *forma
// update the hls time, for hls_dispose.
last_update_time = srs_time_now_cached();
- SrsUniquePtr audio(shared_audio->copy());
+ SrsUniquePtr audio(shared_audio->copy());
// ts support audio codec: aac/mp3
SrsAudioCodecId acodec = format->acodec->id;
@@ -2669,7 +2669,7 @@ srs_error_t SrsHls::on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *forma
return err;
}
-srs_error_t SrsHls::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format)
+srs_error_t SrsHls::on_video(SrsMediaPacket *shared_video, SrsFormat *format)
{
srs_error_t err = srs_success;
@@ -2688,7 +2688,7 @@ srs_error_t SrsHls::on_video(SrsSharedPtrMessage *shared_video, SrsFormat *forma
// update the hls time, for hls_dispose.
last_update_time = srs_time_now_cached();
- SrsUniquePtr video(shared_video->copy());
+ SrsUniquePtr video(shared_video->copy());
// ignore info frame,
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp
index db0258223..f451cdb67 100644
--- a/trunk/src/app/srs_app_hls.hpp
+++ b/trunk/src/app/srs_app_hls.hpp
@@ -19,7 +19,7 @@
#include
class SrsFormat;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsAmf0Object;
class SrsRtmpJitter;
class SrsTsContextWriter;
@@ -117,7 +117,7 @@ public:
public:
virtual srs_error_t initialize(int64_t time, uint32_t v_tid, uint32_t a_tid, int sequence_number, std::string m4s_path);
virtual void config_cipher(unsigned char *key, unsigned char *iv);
- virtual srs_error_t write(SrsSharedPtrMessage *shared_msg, SrsFormat *format);
+ virtual srs_error_t write(SrsMediaPacket *shared_msg, SrsFormat *format);
// Finalizes segment
virtual srs_error_t reap(uint64_t dts);
};
@@ -410,8 +410,8 @@ public:
public:
virtual srs_error_t write_init_mp4(SrsFormat *format, bool has_video, bool has_audio);
- virtual srs_error_t write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
- virtual srs_error_t write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t write_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
+ virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format);
public:
virtual srs_error_t on_unpublish();
@@ -459,11 +459,11 @@ public:
virtual srs_error_t on_unpublish() = 0;
public:
- virtual srs_error_t write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format) = 0;
- virtual srs_error_t write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format) = 0;
+ virtual srs_error_t write_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
+ virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
public:
- virtual srs_error_t on_sequence_header(SrsSharedPtrMessage *msg, SrsFormat *format) = 0;
+ virtual srs_error_t on_sequence_header(SrsMediaPacket *msg, SrsFormat *format) = 0;
virtual int sequence_no() = 0;
// TODO: maybe rename to segment_url?
virtual std::string ts_url() = 0;
@@ -524,11 +524,11 @@ public:
// must write a #EXT-X-DISCONTINUITY to m3u8.
// @see: hls-m3u8-draft-pantos-http-live-streaming-12.txt
// @see: 3.4.11. EXT-X-DISCONTINUITY
- virtual srs_error_t on_sequence_header(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_sequence_header(SrsMediaPacket *shared_audio, SrsFormat *format);
// write audio to cache, if need to flush, flush to muxer.
- virtual srs_error_t write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
+ virtual srs_error_t write_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
// write video to muxer.
- virtual srs_error_t write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format);
private:
// Reopen the muxer for a new hls segment,
@@ -572,11 +572,11 @@ public:
// When publish or unpublish stream.
virtual srs_error_t on_publish(ISrsRequest *req);
virtual srs_error_t on_unpublish();
- virtual srs_error_t write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
- virtual srs_error_t write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t write_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
+ virtual srs_error_t write_video(SrsMediaPacket *shared_video, SrsFormat *format);
public:
- virtual srs_error_t on_sequence_header(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_sequence_header(SrsMediaPacket *shared_audio, SrsFormat *format);
virtual int sequence_no();
virtual std::string ts_url();
virtual srs_utime_t duration();
@@ -637,12 +637,12 @@ public:
virtual void on_unpublish();
// Mux the audio packets to ts.
// @param shared_audio, directly ptr, copy it if need to save it.
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
// Mux the video packets to ts.
// @param shared_video, directly ptr, copy it if need to save it.
// @param is_sps_pps whether the video is h.264 sps/pps.
// TODO: FIXME: Remove param is_sps_pps.
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
private:
virtual void hls_show_mux_log();
diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp
index 3bb3a6e3b..a0bbbe7ac 100644
--- a/trunk/src/app/srs_app_http_conn.hpp
+++ b/trunk/src/app/srs_app_http_conn.hpp
@@ -29,7 +29,7 @@ class SrsHttpParser;
class ISrsHttpMessage;
class SrsHttpHandler;
class SrsMessageQueue;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsFastStream;
class SrsHttpUri;
class SrsHttpMessage;
diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp
index 64019beb1..235f9ef1e 100644
--- a/trunk/src/app/srs_app_http_stream.cpp
+++ b/trunk/src/app/srs_app_http_stream.cpp
@@ -188,7 +188,7 @@ srs_error_t SrsBufferCache::cycle()
// free the messages.
for (int i = 0; i < count; i++) {
- SrsSharedPtrMessage *msg = msgs.msgs[i];
+ SrsMediaPacket *msg = msgs.msgs[i];
queue->enqueue(msg);
}
}
@@ -369,7 +369,7 @@ srs_error_t SrsFlvStreamEncoder::dump_cache(SrsLiveConsumer * /*consumer*/, SrsR
return srs_success;
}
-srs_error_t SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage **msgs, int count)
+srs_error_t SrsFlvStreamEncoder::write_tags(SrsMediaPacket **msgs, int count)
{
srs_error_t err = srs_success;
@@ -390,7 +390,7 @@ srs_error_t SrsFlvStreamEncoder::write_tags(SrsSharedPtrMessage **msgs, int coun
// Note that we must iterate all messages to count the audio and video frames.
for (int i = 0; i < count; i++) {
- SrsSharedPtrMessage *msg = msgs[i];
+ SrsMediaPacket *msg = msgs[i];
if (msg->is_video()) {
if (!SrsFlvVideo::sh(msg->payload(), msg->size()))
nn_video_frames++;
@@ -862,7 +862,7 @@ srs_error_t SrsLiveStream::do_serve_http(SrsLiveSource *source, SrsLiveConsumer
// free the messages.
for (int i = 0; i < count; i++) {
- SrsSharedPtrMessage *msg = msgs.msgs[i];
+ SrsMediaPacket *msg = msgs.msgs[i];
srs_freep(msg);
}
@@ -948,14 +948,14 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage *r)
return;
}
-srs_error_t SrsLiveStream::streaming_send_messages(ISrsBufferEncoder *enc, SrsSharedPtrMessage **msgs, int nb_msgs)
+srs_error_t SrsLiveStream::streaming_send_messages(ISrsBufferEncoder *enc, SrsMediaPacket **msgs, int nb_msgs)
{
srs_error_t err = srs_success;
// TODO: In gop cache, we know both the audio and video codec, so we should notice the encoder, which might depends
// on setting the correct codec information, for example, HTTP-TS or HLS will write PMT.
for (int i = 0; i < nb_msgs; i++) {
- SrsSharedPtrMessage *msg = msgs[i];
+ SrsMediaPacket *msg = msgs[i];
if (msg->is_audio()) {
err = enc->write_audio(msg->timestamp, msg->payload(), msg->size());
diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp
index 64ee5d145..5dce80277 100644
--- a/trunk/src/app/srs_app_http_stream.hpp
+++ b/trunk/src/app/srs_app_http_stream.hpp
@@ -105,7 +105,7 @@ public:
public:
// Write the tags in a time.
- virtual srs_error_t write_tags(SrsSharedPtrMessage **msgs, int count);
+ virtual srs_error_t write_tags(SrsMediaPacket **msgs, int count);
private:
virtual srs_error_t write_header(bool has_video, bool has_audio);
@@ -239,7 +239,7 @@ private:
virtual srs_error_t do_serve_http(SrsLiveSource *source, SrsLiveConsumer *consumer, ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
virtual srs_error_t http_hooks_on_play(ISrsHttpMessage *r);
virtual void http_hooks_on_stop(ISrsHttpMessage *r);
- virtual srs_error_t streaming_send_messages(ISrsBufferEncoder *enc, SrsSharedPtrMessage **msgs, int nb_msgs);
+ virtual srs_error_t streaming_send_messages(ISrsBufferEncoder *enc, SrsMediaPacket **msgs, int nb_msgs);
};
// The Live Entry, to handle HTTP Live Streaming.
diff --git a/trunk/src/app/srs_app_mpegts_udp.cpp b/trunk/src/app/srs_app_mpegts_udp.cpp
index 6b74ee061..11d7fc5b1 100644
--- a/trunk/src/app/srs_app_mpegts_udp.cpp
+++ b/trunk/src/app/srs_app_mpegts_udp.cpp
@@ -84,15 +84,15 @@ SrsMpegtsQueue::SrsMpegtsQueue()
SrsMpegtsQueue::~SrsMpegtsQueue()
{
- std::map::iterator it;
+ std::map::iterator it;
for (it = msgs.begin(); it != msgs.end(); ++it) {
- SrsSharedPtrMessage *msg = it->second;
+ SrsMediaPacket *msg = it->second;
srs_freep(msg);
}
msgs.clear();
}
-srs_error_t SrsMpegtsQueue::push(SrsSharedPtrMessage *msg)
+srs_error_t SrsMpegtsQueue::push(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -125,7 +125,7 @@ srs_error_t SrsMpegtsQueue::push(SrsSharedPtrMessage *msg)
return err;
}
-SrsSharedPtrMessage *SrsMpegtsQueue::dequeue()
+SrsMediaPacket *SrsMpegtsQueue::dequeue()
{
// got 2+ videos and audios, ok to dequeue.
bool av_ok = nb_videos >= 2 && nb_audios >= 2;
@@ -133,8 +133,8 @@ SrsSharedPtrMessage *SrsMpegtsQueue::dequeue()
bool av_overflow = nb_videos > 100 || nb_audios > 300;
if (av_ok || av_overflow) {
- std::map::iterator it = msgs.begin();
- SrsSharedPtrMessage *msg = it->second;
+ std::map::iterator it = msgs.begin();
+ SrsMediaPacket *msg = it->second;
msgs.erase(it);
if (msg->is_audio()) {
@@ -604,12 +604,15 @@ srs_error_t SrsMpegtsOverUdp::rtmp_write_packet(char type, uint32_t timestamp, c
return srs_error_wrap(err, "connect");
}
- SrsSharedPtrMessage *msg = NULL;
-
- if ((err = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &msg)) != srs_success) {
+ SrsCommonMessage *cmsg = NULL;
+ if ((err = srs_rtmp_create_msg(type, timestamp, data, size, sdk->sid(), &cmsg)) != srs_success) {
return srs_error_wrap(err, "create message");
}
- srs_assert(msg);
+ srs_assert(cmsg);
+
+ SrsMediaPacket *msg = new SrsMediaPacket();
+ cmsg->to_msg(msg);
+ srs_freep(cmsg);
// push msg to queue.
if ((err = queue->push(msg)) != srs_success) {
diff --git a/trunk/src/app/srs_app_mpegts_udp.hpp b/trunk/src/app/srs_app_mpegts_udp.hpp
index c8cd8faee..62dc3d46e 100644
--- a/trunk/src/app/srs_app_mpegts_udp.hpp
+++ b/trunk/src/app/srs_app_mpegts_udp.hpp
@@ -21,7 +21,7 @@ class SrsRtmpClient;
class SrsStSocket;
class ISrsRequest;
class SrsRawH264Stream;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsRawAacStream;
struct SrsRawAacStreamCodec;
class SrsPithyPrint;
@@ -56,7 +56,7 @@ class SrsMpegtsQueue
{
private:
// The key: dts, value: msg.
- std::map msgs;
+ std::map msgs;
int nb_audios;
int nb_videos;
@@ -65,8 +65,8 @@ public:
virtual ~SrsMpegtsQueue();
public:
- virtual srs_error_t push(SrsSharedPtrMessage *msg);
- virtual SrsSharedPtrMessage *dequeue();
+ virtual srs_error_t push(SrsMediaPacket *msg);
+ virtual SrsMediaPacket *dequeue();
};
// The mpegts over udp stream caster.
diff --git a/trunk/src/app/srs_app_rtc_codec.cpp b/trunk/src/app/srs_app_rtc_codec.cpp
index 4ad118101..e2fb2a821 100644
--- a/trunk/src/app/srs_app_rtc_codec.cpp
+++ b/trunk/src/app/srs_app_rtc_codec.cpp
@@ -159,7 +159,7 @@ srs_error_t SrsAudioTranscoder::initialize(SrsAudioCodecId src_codec, SrsAudioCo
return err;
}
-srs_error_t SrsAudioTranscoder::transcode(SrsAudioFrame *in_pkt, std::vector &out_pkts)
+srs_error_t SrsAudioTranscoder::transcode(SrsParsedAudioPacket *in_pkt, std::vector &out_pkts)
{
srs_error_t err = srs_success;
@@ -174,10 +174,10 @@ srs_error_t SrsAudioTranscoder::transcode(SrsAudioFrame *in_pkt, std::vector &frames)
+void SrsAudioTranscoder::free_frames(std::vector &frames)
{
- for (std::vector::iterator it = frames.begin(); it != frames.end(); ++it) {
- SrsAudioFrame *p = *it;
+ for (std::vector::iterator it = frames.begin(); it != frames.end(); ++it) {
+ SrsParsedAudioPacket *p = *it;
for (int i = 0; i < p->nb_samples; i++) {
char *pa = p->samples[i].bytes;
@@ -325,7 +325,7 @@ srs_error_t SrsAudioTranscoder::init_fifo()
return srs_success;
}
-srs_error_t SrsAudioTranscoder::decode_and_resample(SrsAudioFrame *pkt)
+srs_error_t SrsAudioTranscoder::decode_and_resample(SrsParsedAudioPacket *pkt)
{
srs_error_t err = srs_success;
@@ -380,7 +380,7 @@ srs_error_t SrsAudioTranscoder::decode_and_resample(SrsAudioFrame *pkt)
return err;
}
-srs_error_t SrsAudioTranscoder::encode(std::vector &pkts)
+srs_error_t SrsAudioTranscoder::encode(std::vector &pkts)
{
char err_buf[AV_ERROR_MAX_STRING_SIZE] = {0};
@@ -435,7 +435,7 @@ srs_error_t SrsAudioTranscoder::encode(std::vector &pkts)
enc_packet_->dts = av_rescale(enc_packet_->dts, 1000, enc_->time_base.den);
enc_packet_->pts = av_rescale(enc_packet_->pts, 1000, enc_->time_base.den);
- SrsAudioFrame *out_frame = new SrsAudioFrame;
+ SrsParsedAudioPacket *out_frame = new SrsParsedAudioPacket;
char *buf = new char[enc_packet_->size];
memcpy(buf, enc_packet_->data, enc_packet_->size);
out_frame->add_sample(buf, enc_packet_->size);
diff --git a/trunk/src/app/srs_app_rtc_codec.hpp b/trunk/src/app/srs_app_rtc_codec.hpp
index 5b6c8fab8..9837c7997 100644
--- a/trunk/src/app/srs_app_rtc_codec.hpp
+++ b/trunk/src/app/srs_app_rtc_codec.hpp
@@ -10,6 +10,7 @@
#include
#include
+#include
#include
@@ -60,9 +61,9 @@ public:
// The bit_rate specifies the bitrate of encoder, for example, 48000.
srs_error_t initialize(SrsAudioCodecId from, SrsAudioCodecId to, int channels, int sample_rate, int bit_rate);
// Transcode the input audio frame in, as output audio frames outs.
- virtual srs_error_t transcode(SrsAudioFrame *in, std::vector &outs);
+ virtual srs_error_t transcode(SrsParsedAudioPacket *in, std::vector &outs);
// Free the generated audio frames by transcode.
- void free_frames(std::vector &frames);
+ void free_frames(std::vector &frames);
public:
// Get the aac codec header, for example, FLV sequence header.
@@ -75,8 +76,8 @@ private:
srs_error_t init_swr(AVCodecContext *decoder);
srs_error_t init_fifo();
- srs_error_t decode_and_resample(SrsAudioFrame *pkt);
- srs_error_t encode(std::vector &pkts);
+ srs_error_t decode_and_resample(SrsParsedAudioPacket *pkt);
+ srs_error_t encode(std::vector &pkts);
srs_error_t add_samples_to_fifo(uint8_t **samples, int frame_size);
void free_swr_samples();
diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp
index 40b3ce927..03eca542d 100644
--- a/trunk/src/app/srs_app_rtc_conn.hpp
+++ b/trunk/src/app/srs_app_rtc_conn.hpp
@@ -35,7 +35,7 @@ class SrsLiveConsumer;
class SrsStunPacket;
class SrsServer;
class SrsRtcConnection;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsRtcSource;
class SrsRtpPacket;
class ISrsCodec;
diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp
index bd73043b6..f806f8343 100644
--- a/trunk/src/app/srs_app_rtc_source.cpp
+++ b/trunk/src/app/srs_app_rtc_source.cpp
@@ -68,7 +68,7 @@ using namespace std;
#define SRS_RTC_SOURCE_CLEANUP (3 * SRS_UTIME_SECONDS)
// TODO: Add this function into SrsRtpMux class.
-srs_error_t aac_raw_append_adts_header(SrsSharedPtrMessage *shared_audio, SrsFormat *format, char **pbuf, int *pnn_buf)
+srs_error_t aac_raw_append_adts_header(SrsMediaPacket *shared_audio, SrsFormat *format, char **pbuf, int *pnn_buf)
{
srs_error_t err = srs_success;
@@ -1005,7 +1005,7 @@ void SrsRtcRtpBuilder::on_unpublish()
meta->update_previous_ash();
}
-srs_error_t SrsRtcRtpBuilder::on_frame(SrsSharedPtrMessage *frame)
+srs_error_t SrsRtcRtpBuilder::on_frame(SrsMediaPacket *frame)
{
if (frame->is_audio()) {
return on_audio(frame);
@@ -1015,7 +1015,7 @@ srs_error_t SrsRtcRtpBuilder::on_frame(SrsSharedPtrMessage *frame)
return srs_success;
}
-srs_error_t SrsRtcRtpBuilder::on_audio(SrsSharedPtrMessage *msg)
+srs_error_t SrsRtcRtpBuilder::on_audio(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -1072,7 +1072,7 @@ srs_error_t SrsRtcRtpBuilder::on_audio(SrsSharedPtrMessage *msg)
return err;
}
- SrsAudioFrame aac;
+ SrsParsedAudioPacket aac;
aac.dts = format->audio->dts;
aac.cts = format->audio->cts;
if ((err = aac.add_sample(adts_audio, nn_adts_audio)) == srs_success) {
@@ -1115,11 +1115,11 @@ srs_error_t SrsRtcRtpBuilder::init_codec(SrsAudioCodecId codec)
return err;
}
-srs_error_t SrsRtcRtpBuilder::transcode(SrsAudioFrame *audio)
+srs_error_t SrsRtcRtpBuilder::transcode(SrsParsedAudioPacket *audio)
{
srs_error_t err = srs_success;
- std::vector out_audios;
+ std::vector out_audios;
if ((err = codec_->transcode(audio, out_audios)) != srs_success) {
return srs_error_wrap(err, "recode error");
}
@@ -1129,8 +1129,8 @@ srs_error_t SrsRtcRtpBuilder::transcode(SrsAudioFrame *audio)
return err;
}
- for (std::vector::iterator it = out_audios.begin(); it != out_audios.end(); ++it) {
- SrsAudioFrame *out_audio = *it;
+ for (std::vector::iterator it = out_audios.begin(); it != out_audios.end(); ++it) {
+ SrsParsedAudioPacket *out_audio = *it;
SrsUniquePtr pkt(new SrsRtpPacket());
if ((err = package_opus(out_audio, pkt.get())) != srs_success) {
@@ -1149,7 +1149,7 @@ srs_error_t SrsRtcRtpBuilder::transcode(SrsAudioFrame *audio)
return err;
}
-srs_error_t SrsRtcRtpBuilder::package_opus(SrsAudioFrame *audio, SrsRtpPacket *pkt)
+srs_error_t SrsRtcRtpBuilder::package_opus(SrsParsedAudioPacket *audio, SrsRtpPacket *pkt)
{
srs_error_t err = srs_success;
@@ -1181,7 +1181,7 @@ static void free_packets(vector *pkts)
pkts->clear();
}
-srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage *msg)
+srs_error_t SrsRtcRtpBuilder::on_video(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -1216,7 +1216,7 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage *msg)
}
bool has_idr = false;
- vector samples;
+ vector samples;
if ((err = filter(msg, format, has_idr, samples)) != srs_success) {
return srs_error_wrap(err, "filter video");
}
@@ -1247,7 +1247,7 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage *msg)
} else {
// By default, we package each NALU(sample) to a RTP or FUA packet.
for (int i = 0; i < nn_samples; i++) {
- SrsSample *sample = samples[i];
+ SrsNaluSample *sample = samples[i];
if (sample->size <= kRtpMaxPayloadSize) {
if ((err = package_single_nalu(msg, sample, pkts)) != srs_success) {
@@ -1268,7 +1268,7 @@ srs_error_t SrsRtcRtpBuilder::on_video(SrsSharedPtrMessage *msg)
return consume_packets(pkts);
}
-srs_error_t SrsRtcRtpBuilder::filter(SrsSharedPtrMessage *msg, SrsFormat *format, bool &has_idr, vector &samples)
+srs_error_t SrsRtcRtpBuilder::filter(SrsMediaPacket *msg, SrsFormat *format, bool &has_idr, vector &samples)
{
srs_error_t err = srs_success;
@@ -1279,12 +1279,12 @@ srs_error_t SrsRtcRtpBuilder::filter(SrsSharedPtrMessage *msg, SrsFormat *format
// Update samples to shared frame.
for (int i = 0; i < format->video->nb_samples; ++i) {
- SrsSample *sample = &format->video->samples[i];
+ SrsNaluSample *sample = &format->video->samples[i];
if (!keep_avc_nalu_sei && format->vcodec->id == SrsVideoCodecIdAVC) {
SrsAvcNaluType avc_nalu_type;
- if ((err = SrsVideoFrame::parse_avc_nalu_type(sample, avc_nalu_type)) != srs_success) {
+ if ((err = SrsParsedVideoPacket::parse_avc_nalu_type(sample, avc_nalu_type)) != srs_success) {
return srs_error_wrap(err, "parse avc nalu_type");
}
if (avc_nalu_type == SrsAvcNaluTypeSEI) {
@@ -1298,11 +1298,11 @@ srs_error_t SrsRtcRtpBuilder::filter(SrsSharedPtrMessage *msg, SrsFormat *format
if (!keep_bframe) {
bool is_b_frame = false;
if (format->vcodec->id == SrsVideoCodecIdAVC) {
- if ((err = SrsVideoFrame::parse_avc_bframe(sample, is_b_frame)) != srs_success) {
+ if ((err = SrsParsedVideoPacket::parse_avc_bframe(sample, is_b_frame)) != srs_success) {
return srs_error_wrap(err, "parse bframe");
}
} else if (format->vcodec->id == SrsVideoCodecIdHEVC) {
- if ((err = SrsVideoFrame::parse_hevc_bframe(sample, format, is_b_frame)) != srs_success) {
+ if ((err = SrsParsedVideoPacket::parse_hevc_bframe(sample, format, is_b_frame)) != srs_success) {
return srs_error_wrap(err, "parse bframe");
}
}
@@ -1317,7 +1317,7 @@ srs_error_t SrsRtcRtpBuilder::filter(SrsSharedPtrMessage *msg, SrsFormat *format
return err;
}
-srs_error_t SrsRtcRtpBuilder::package_stap_a(SrsSharedPtrMessage *msg, SrsRtpPacket *pkt)
+srs_error_t SrsRtcRtpBuilder::package_stap_a(SrsMediaPacket *msg, SrsRtpPacket *pkt)
{
srs_error_t err = srs_success;
@@ -1329,7 +1329,7 @@ srs_error_t SrsRtcRtpBuilder::package_stap_a(SrsSharedPtrMessage *msg, SrsRtpPac
return video_builder_->package_stap_a(msg, pkt);
}
-srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage *msg, const vector &samples, vector &pkts)
+srs_error_t SrsRtcRtpBuilder::package_nalus(SrsMediaPacket *msg, const vector &samples, vector &pkts)
{
srs_error_t err = srs_success;
@@ -1342,12 +1342,12 @@ srs_error_t SrsRtcRtpBuilder::package_nalus(SrsSharedPtrMessage *msg, const vect
}
// Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6
-srs_error_t SrsRtcRtpBuilder::package_single_nalu(SrsSharedPtrMessage *msg, SrsSample *sample, vector &pkts)
+srs_error_t SrsRtcRtpBuilder::package_single_nalu(SrsMediaPacket *msg, SrsNaluSample *sample, vector &pkts)
{
return video_builder_->package_single_nalu(msg, sample, pkts);
}
-srs_error_t SrsRtcRtpBuilder::package_fu_a(SrsSharedPtrMessage *msg, SrsSample *sample, int fu_payload_size, vector &pkts)
+srs_error_t SrsRtcRtpBuilder::package_fu_a(SrsMediaPacket *msg, SrsNaluSample *sample, int fu_payload_size, vector &pkts)
{
srs_error_t err = srs_success;
@@ -1867,10 +1867,8 @@ srs_error_t SrsRtcFrameBuilder::transcode_audio(SrsRtpPacket *pkt)
SrsCommonMessage out_rtmp;
packet_aac(&out_rtmp, (char *)header, header_len, ts, is_first_audio_);
- SrsSharedPtrMessage msg;
- if ((err = msg.create(&out_rtmp)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ out_rtmp.to_msg(&msg);
if ((err = bridge_->on_frame(&msg)) != srs_success) {
return srs_error_wrap(err, "source on audio");
@@ -1880,10 +1878,10 @@ srs_error_t SrsRtcFrameBuilder::transcode_audio(SrsRtpPacket *pkt)
}
// TODO: FIXME: Should use SrsUniquePtr to dispose it automatically.
- std::vector out_pkts;
+ std::vector out_pkts;
SrsRtpRawPayload *payload = dynamic_cast(pkt->payload());
- SrsAudioFrame frame;
+ SrsParsedAudioPacket frame;
frame.add_sample(payload->payload, payload->nn_payload);
frame.dts = ts;
frame.cts = 0;
@@ -1893,16 +1891,14 @@ srs_error_t SrsRtcFrameBuilder::transcode_audio(SrsRtpPacket *pkt)
return err;
}
- for (std::vector::iterator it = out_pkts.begin(); it != out_pkts.end(); ++it) {
+ for (std::vector::iterator it = out_pkts.begin(); it != out_pkts.end(); ++it) {
SrsCommonMessage out_rtmp;
// TODO: FIXME: Should never directly use it, please define a variable with class name.
out_rtmp.header.timestamp = (*it)->dts;
packet_aac(&out_rtmp, (*it)->samples[0].bytes, (*it)->samples[0].size, ts, is_first_audio_);
- SrsSharedPtrMessage msg;
- if ((err = msg.create(&out_rtmp)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ out_rtmp.to_msg(&msg);
if ((err = bridge_->on_frame(&msg)) != srs_success) {
err = srs_error_wrap(err, "source on audio");
@@ -2023,10 +2019,10 @@ srs_error_t SrsRtcFrameBuilder::packet_sequence_header_avc(SrsRtpPacket *pkt)
// Handle SPS/PPS in cache or STAP-A packet.
if (stap_payload || has_sps_pps_in_raw_payload) {
// Get the SPS/PPS from cache or STAP-A packet.
- SrsSample *sps = stap_payload ? stap_payload->get_sps() : NULL;
+ SrsNaluSample *sps = stap_payload ? stap_payload->get_sps() : NULL;
if (!sps && obs_whip_sps_)
sps = dynamic_cast(obs_whip_sps_->payload())->sample_;
- SrsSample *pps = stap_payload ? stap_payload->get_pps() : NULL;
+ SrsNaluSample *pps = stap_payload ? stap_payload->get_pps() : NULL;
if (!pps && obs_whip_pps_)
pps = dynamic_cast(obs_whip_pps_->payload())->sample_;
if (!sps || !pps) {
@@ -2048,7 +2044,7 @@ srs_error_t SrsRtcFrameBuilder::packet_sequence_header_avc(SrsRtpPacket *pkt)
return err;
}
-srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_avc(SrsRtpPacket *pkt, SrsSample *sps, SrsSample *pps)
+srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_avc(SrsRtpPacket *pkt, SrsNaluSample *sps, SrsNaluSample *pps)
{
srs_error_t err = srs_success;
@@ -2078,10 +2074,8 @@ srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_avc(SrsRtpPacket *pkt,
return srs_error_wrap(err, "create rtmp");
}
- SrsSharedPtrMessage msg;
- if ((err = msg.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ rtmp.to_msg(&msg);
if ((err = bridge_->on_frame(&msg)) != srs_success) {
return err;
@@ -2121,13 +2115,13 @@ srs_error_t SrsRtcFrameBuilder::packet_sequence_header_hevc(SrsRtpPacket *pkt)
// Generally, there will be SPS+PPS+IDR in a STAP-A packet.
SrsRtpSTAPPayloadHevc *stap_payload_hevc = dynamic_cast(pkt->payload());
if (video_codec_ == SrsVideoCodecIdHEVC && (stap_payload_hevc || has_vps_sps_pps_in_raw_payload)) {
- SrsSample *vps = stap_payload_hevc ? stap_payload_hevc->get_vps() : NULL;
+ SrsNaluSample *vps = stap_payload_hevc ? stap_payload_hevc->get_vps() : NULL;
if (!vps && obs_whip_vps_)
vps = dynamic_cast(obs_whip_vps_->payload())->sample_;
- SrsSample *sps = stap_payload_hevc ? stap_payload_hevc->get_sps() : NULL;
+ SrsNaluSample *sps = stap_payload_hevc ? stap_payload_hevc->get_sps() : NULL;
if (!sps && obs_whip_sps_)
sps = dynamic_cast(obs_whip_sps_->payload())->sample_;
- SrsSample *pps = stap_payload_hevc ? stap_payload_hevc->get_pps() : NULL;
+ SrsNaluSample *pps = stap_payload_hevc ? stap_payload_hevc->get_pps() : NULL;
if (!pps && obs_whip_pps_)
pps = dynamic_cast(obs_whip_pps_->payload())->sample_;
if (!vps || !sps || !pps) {
@@ -2149,7 +2143,7 @@ srs_error_t SrsRtcFrameBuilder::packet_sequence_header_hevc(SrsRtpPacket *pkt)
return err;
}
-srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_hevc(SrsRtpPacket *pkt, SrsSample *vps, SrsSample *sps, SrsSample *pps)
+srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_hevc(SrsRtpPacket *pkt, SrsNaluSample *vps, SrsNaluSample *sps, SrsNaluSample *pps)
{
srs_error_t err = srs_success;
@@ -2177,10 +2171,8 @@ srs_error_t SrsRtcFrameBuilder::do_packet_sequence_header_hevc(SrsRtpPacket *pkt
return srs_error_wrap(err, "create rtmp");
}
- SrsSharedPtrMessage msg;
- if ((err = msg.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ rtmp.to_msg(&msg);
if ((err = bridge_->on_frame(&msg)) != srs_success) {
return err;
@@ -2210,7 +2202,7 @@ int SrsRtcFrameBuilder::calculate_packet_payload_size(SrsRtpPacket *pkt)
if (stap_payload) {
int size = 0;
for (int j = 0; j < (int)stap_payload->nalus.size(); ++j) {
- SrsSample *sample = stap_payload->nalus.at(j);
+ SrsNaluSample *sample = stap_payload->nalus.at(j);
if (sample->size > 0) {
size += 4 + sample->size; // length prefix + NALU
}
@@ -2233,7 +2225,7 @@ int SrsRtcFrameBuilder::calculate_packet_payload_size(SrsRtpPacket *pkt)
if (stap_payload_hevc) {
int size = 0;
for (int j = 0; j < (int)stap_payload_hevc->nalus.size(); ++j) {
- SrsSample *sample = stap_payload_hevc->nalus.at(j);
+ SrsNaluSample *sample = stap_payload_hevc->nalus.at(j);
if (sample->size > 0) {
size += 4 + sample->size; // length prefix + NALU
}
@@ -2281,7 +2273,7 @@ void SrsRtcFrameBuilder::write_packet_payload_to_buffer(SrsRtpPacket *pkt, SrsBu
SrsRtpSTAPPayload *stap_payload = dynamic_cast(pkt->payload());
if (stap_payload) {
for (int j = 0; j < (int)stap_payload->nalus.size(); ++j) {
- SrsSample *sample = stap_payload->nalus.at(j);
+ SrsNaluSample *sample = stap_payload->nalus.at(j);
if (sample->size > 0) {
payload.write_4bytes(sample->size);
payload.write_bytes(sample->bytes, sample->size);
@@ -2316,7 +2308,7 @@ void SrsRtcFrameBuilder::write_packet_payload_to_buffer(SrsRtpPacket *pkt, SrsBu
SrsRtpSTAPPayloadHevc *stap_payload_hevc = dynamic_cast(pkt->payload());
if (stap_payload_hevc) {
for (int j = 0; j < (int)stap_payload_hevc->nalus.size(); ++j) {
- SrsSample *sample = stap_payload_hevc->nalus.at(j);
+ SrsNaluSample *sample = stap_payload_hevc->nalus.at(j);
if (sample->size > 0) {
payload.write_4bytes(sample->size);
payload.write_bytes(sample->bytes, sample->size);
@@ -2435,10 +2427,8 @@ srs_error_t SrsRtcFrameBuilder::packet_video_rtmp(const uint16_t start, const ui
write_packet_payload_to_buffer(pkt.get(), payload, nalu_len);
}
- SrsSharedPtrMessage msg;
- if ((err = msg.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ rtmp.to_msg(&msg);
if ((err = bridge_->on_frame(&msg)) != srs_success) {
srs_warn("fail to pack video frame: %s", srs_error_summary(err).c_str());
diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp
index 8c98fa5ac..55752cb9f 100644
--- a/trunk/src/app/srs_app_rtc_source.hpp
+++ b/trunk/src/app/srs_app_rtc_source.hpp
@@ -24,14 +24,14 @@
class ISrsRequest;
class SrsMetaCache;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsCommonMessage;
class SrsMessageArray;
class SrsRtcSource;
class SrsFrameToRtcBridge;
class SrsAudioTranscoder;
class SrsRtpPacket;
-class SrsSample;
+class SrsNaluSample;
class SrsRtcSourceDescription;
class SrsRtcTrackDescription;
class SrsRtcConnection;
@@ -346,25 +346,25 @@ public:
virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
+ virtual srs_error_t on_frame(SrsMediaPacket *frame);
private:
- virtual srs_error_t on_audio(SrsSharedPtrMessage *msg);
+ virtual srs_error_t on_audio(SrsMediaPacket *msg);
private:
srs_error_t init_codec(SrsAudioCodecId codec);
- srs_error_t transcode(SrsAudioFrame *audio);
- srs_error_t package_opus(SrsAudioFrame *audio, SrsRtpPacket *pkt);
+ srs_error_t transcode(SrsParsedAudioPacket *audio);
+ srs_error_t package_opus(SrsParsedAudioPacket *audio, SrsRtpPacket *pkt);
private:
- virtual srs_error_t on_video(SrsSharedPtrMessage *msg);
+ virtual srs_error_t on_video(SrsMediaPacket *msg);
private:
- srs_error_t filter(SrsSharedPtrMessage *msg, SrsFormat *format, bool &has_idr, std::vector &samples);
- srs_error_t package_stap_a(SrsSharedPtrMessage *msg, SrsRtpPacket *pkt);
- srs_error_t package_nalus(SrsSharedPtrMessage *msg, const std::vector &samples, std::vector &pkts);
- srs_error_t package_single_nalu(SrsSharedPtrMessage *msg, SrsSample *sample, std::vector &pkts);
- srs_error_t package_fu_a(SrsSharedPtrMessage *msg, SrsSample *sample, int fu_payload_size, std::vector &pkts);
+ srs_error_t filter(SrsMediaPacket *msg, SrsFormat *format, bool &has_idr, std::vector &samples);
+ srs_error_t package_stap_a(SrsMediaPacket *msg, SrsRtpPacket *pkt);
+ srs_error_t package_nalus(SrsMediaPacket *msg, const std::vector &samples, std::vector &pkts);
+ srs_error_t package_single_nalu(SrsMediaPacket *msg, SrsNaluSample *sample, std::vector &pkts);
+ srs_error_t package_fu_a(SrsMediaPacket *msg, SrsNaluSample *sample, int fu_payload_size, std::vector &pkts);
srs_error_t consume_packets(std::vector &pkts);
};
@@ -504,9 +504,9 @@ private:
srs_error_t packet_video(SrsRtpPacket *pkt);
srs_error_t packet_video_key_frame(SrsRtpPacket *pkt);
srs_error_t packet_sequence_header_avc(SrsRtpPacket *pkt);
- srs_error_t do_packet_sequence_header_avc(SrsRtpPacket *pkt, SrsSample *sps, SrsSample *pps);
+ srs_error_t do_packet_sequence_header_avc(SrsRtpPacket *pkt, SrsNaluSample *sps, SrsNaluSample *pps);
srs_error_t packet_sequence_header_hevc(SrsRtpPacket *pkt);
- srs_error_t do_packet_sequence_header_hevc(SrsRtpPacket *pkt, SrsSample *vps, SrsSample *sps, SrsSample *pps);
+ srs_error_t do_packet_sequence_header_hevc(SrsRtpPacket *pkt, SrsNaluSample *vps, SrsNaluSample *sps, SrsNaluSample *pps);
private:
srs_error_t packet_video_rtmp(const uint16_t start, const uint16_t end);
diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp
index cf7bdb6a9..c7825bd81 100644
--- a/trunk/src/app/srs_app_rtmp_conn.cpp
+++ b/trunk/src/app/srs_app_rtmp_conn.cpp
@@ -825,7 +825,7 @@ srs_error_t SrsRtmpConn::do_playing(SrsSharedPtr source, SrsLiveC
// we start to collect the durations for each message.
if (user_specified_duration_to_stop) {
for (int i = 0; i < count; i++) {
- SrsSharedPtrMessage *msg = msgs.msgs[i];
+ SrsMediaPacket *msg = msgs.msgs[i];
// foreach msg, collect the duration.
// @remark: never use msg when sent it, for the protocol sdk will free it.
@@ -1109,11 +1109,11 @@ srs_error_t SrsRtmpConn::handle_publish_message(SrsSharedPtr &sou
// process publish event.
if (msg->header.is_amf0_command() || msg->header.is_amf3_command()) {
- SrsPacket *pkt_raw = NULL;
+ SrsRtmpCommand *pkt_raw = NULL;
if ((err = rtmp->decode_message(msg, &pkt_raw)) != srs_success) {
return srs_error_wrap(err, "rtmp: decode message");
}
- SrsUniquePtr pkt(pkt_raw);
+ SrsUniquePtr pkt(pkt_raw);
// for flash, any packet is republish.
if (info->type == SrsRtmpConnFlashPublish) {
@@ -1181,11 +1181,11 @@ srs_error_t SrsRtmpConn::process_publish_message(SrsSharedPtr &so
// process onMetaData
if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
- SrsPacket *pkt_raw = NULL;
+ SrsRtmpCommand *pkt_raw = NULL;
if ((err = rtmp->decode_message(msg, &pkt_raw)) != srs_success) {
return srs_error_wrap(err, "rtmp: decode message");
}
- SrsUniquePtr pkt(pkt_raw);
+ SrsUniquePtr pkt(pkt_raw);
if (dynamic_cast(pkt.get())) {
SrsOnMetaDataPacket *metadata = dynamic_cast(pkt.get());
@@ -1213,11 +1213,11 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsLiveConsumer *consumer, Srs
return err;
}
- SrsPacket *pkt_raw = NULL;
+ SrsRtmpCommand *pkt_raw = NULL;
if ((err = rtmp->decode_message(msg.get(), &pkt_raw)) != srs_success) {
return srs_error_wrap(err, "rtmp: decode message");
}
- SrsUniquePtr pkt(pkt_raw);
+ SrsUniquePtr pkt(pkt_raw);
// for jwplayer/flowplayer, which send close as pause message.
SrsCloseStreamPacket *close = dynamic_cast(pkt.get());
diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp
index 00752f9c2..370851385 100644
--- a/trunk/src/app/srs_app_rtmp_conn.hpp
+++ b/trunk/src/app/srs_app_rtmp_conn.hpp
@@ -31,13 +31,13 @@ class SrsHttpHooks;
class SrsBandwidth;
class SrsKbps;
class SrsRtmpClient;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsQueueRecvThread;
class SrsPublishRecvThread;
class SrsSecurity;
class ISrsWakable;
class SrsCommonMessage;
-class SrsPacket;
+class SrsRtmpCommand;
class SrsNetworkDelta;
class SrsSslConnection;
diff --git a/trunk/src/app/srs_app_rtsp_source.cpp b/trunk/src/app/srs_app_rtsp_source.cpp
index 7912c8cc2..22ed3478c 100644
--- a/trunk/src/app/srs_app_rtsp_source.cpp
+++ b/trunk/src/app/srs_app_rtsp_source.cpp
@@ -692,7 +692,7 @@ void SrsRtspRtpBuilder::on_unpublish()
meta->update_previous_ash();
}
-srs_error_t SrsRtspRtpBuilder::on_frame(SrsSharedPtrMessage *frame)
+srs_error_t SrsRtspRtpBuilder::on_frame(SrsMediaPacket *frame)
{
if (frame->is_audio()) {
return on_audio(frame);
@@ -702,7 +702,7 @@ srs_error_t SrsRtspRtpBuilder::on_frame(SrsSharedPtrMessage *frame)
return srs_success;
}
-srs_error_t SrsRtspRtpBuilder::on_audio(SrsSharedPtrMessage *msg)
+srs_error_t SrsRtspRtpBuilder::on_audio(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -753,7 +753,7 @@ srs_error_t SrsRtspRtpBuilder::on_audio(SrsSharedPtrMessage *msg)
return err;
}
-srs_error_t SrsRtspRtpBuilder::package_aac(SrsAudioFrame *audio, SrsRtpPacket *pkt)
+srs_error_t SrsRtspRtpBuilder::package_aac(SrsParsedAudioPacket *audio, SrsRtpPacket *pkt)
{
srs_error_t err = srs_success;
@@ -827,7 +827,7 @@ static void free_packets(vector *pkts)
pkts->clear();
}
-srs_error_t SrsRtspRtpBuilder::on_video(SrsSharedPtrMessage *msg)
+srs_error_t SrsRtspRtpBuilder::on_video(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -862,7 +862,7 @@ srs_error_t SrsRtspRtpBuilder::on_video(SrsSharedPtrMessage *msg)
}
bool has_idr = false;
- vector samples;
+ vector samples;
if ((err = filter(msg, format, has_idr, samples)) != srs_success) {
return srs_error_wrap(err, "filter video");
}
@@ -888,7 +888,7 @@ srs_error_t SrsRtspRtpBuilder::on_video(SrsSharedPtrMessage *msg)
// By default, we package each NALU(sample) to a RTP or FUA packet.
for (int i = 0; i < nn_samples; i++) {
- SrsSample *sample = samples[i];
+ SrsNaluSample *sample = samples[i];
if (sample->size <= kRtpMaxPayloadSize) {
if ((err = package_single_nalu(msg, sample, pkts)) != srs_success) {
@@ -908,7 +908,7 @@ srs_error_t SrsRtspRtpBuilder::on_video(SrsSharedPtrMessage *msg)
return consume_packets(pkts);
}
-srs_error_t SrsRtspRtpBuilder::filter(SrsSharedPtrMessage *msg, SrsFormat *format, bool &has_idr, vector &samples)
+srs_error_t SrsRtspRtpBuilder::filter(SrsMediaPacket *msg, SrsFormat *format, bool &has_idr, vector &samples)
{
srs_error_t err = srs_success;
@@ -919,14 +919,14 @@ srs_error_t SrsRtspRtpBuilder::filter(SrsSharedPtrMessage *msg, SrsFormat *forma
// Update samples to shared frame.
for (int i = 0; i < format->video->nb_samples; ++i) {
- SrsSample *sample = &format->video->samples[i];
+ SrsNaluSample *sample = &format->video->samples[i];
samples.push_back(sample);
}
return err;
}
-srs_error_t SrsRtspRtpBuilder::package_stap_a(SrsSharedPtrMessage *msg, SrsRtpPacket *pkt)
+srs_error_t SrsRtspRtpBuilder::package_stap_a(SrsMediaPacket *msg, SrsRtpPacket *pkt)
{
srs_error_t err = srs_success;
@@ -938,7 +938,7 @@ srs_error_t SrsRtspRtpBuilder::package_stap_a(SrsSharedPtrMessage *msg, SrsRtpPa
return video_builder_->package_stap_a(msg, pkt);
}
-srs_error_t SrsRtspRtpBuilder::package_nalus(SrsSharedPtrMessage *msg, const vector &samples, vector &pkts)
+srs_error_t SrsRtspRtpBuilder::package_nalus(SrsMediaPacket *msg, const vector &samples, vector &pkts)
{
srs_error_t err = srs_success;
@@ -951,12 +951,12 @@ srs_error_t SrsRtspRtpBuilder::package_nalus(SrsSharedPtrMessage *msg, const vec
}
// Single NAL Unit Packet @see https://tools.ietf.org/html/rfc6184#section-5.6
-srs_error_t SrsRtspRtpBuilder::package_single_nalu(SrsSharedPtrMessage *msg, SrsSample *sample, vector &pkts)
+srs_error_t SrsRtspRtpBuilder::package_single_nalu(SrsMediaPacket *msg, SrsNaluSample *sample, vector &pkts)
{
return video_builder_->package_single_nalu(msg, sample, pkts);
}
-srs_error_t SrsRtspRtpBuilder::package_fu_a(SrsSharedPtrMessage *msg, SrsSample *sample, int fu_payload_size, vector &pkts)
+srs_error_t SrsRtspRtpBuilder::package_fu_a(SrsMediaPacket *msg, SrsNaluSample *sample, int fu_payload_size, vector &pkts)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_rtsp_source.hpp b/trunk/src/app/srs_app_rtsp_source.hpp
index 3bb40b209..6a21a3fb8 100644
--- a/trunk/src/app/srs_app_rtsp_source.hpp
+++ b/trunk/src/app/srs_app_rtsp_source.hpp
@@ -223,23 +223,23 @@ public:
virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
+ virtual srs_error_t on_frame(SrsMediaPacket *frame);
private:
- virtual srs_error_t on_audio(SrsSharedPtrMessage *msg);
+ virtual srs_error_t on_audio(SrsMediaPacket *msg);
private:
- srs_error_t package_aac(SrsAudioFrame *audio, SrsRtpPacket *pkt);
+ srs_error_t package_aac(SrsParsedAudioPacket *audio, SrsRtpPacket *pkt);
private:
- virtual srs_error_t on_video(SrsSharedPtrMessage *msg);
+ virtual srs_error_t on_video(SrsMediaPacket *msg);
private:
- srs_error_t filter(SrsSharedPtrMessage *msg, SrsFormat *format, bool &has_idr, std::vector &samples);
- srs_error_t package_stap_a(SrsSharedPtrMessage *msg, SrsRtpPacket *pkt);
- srs_error_t package_nalus(SrsSharedPtrMessage *msg, const std::vector &samples, std::vector &pkts);
- srs_error_t package_single_nalu(SrsSharedPtrMessage *msg, SrsSample *sample, std::vector &pkts);
- srs_error_t package_fu_a(SrsSharedPtrMessage *msg, SrsSample *sample, int fu_payload_size, std::vector &pkts);
+ srs_error_t filter(SrsMediaPacket *msg, SrsFormat *format, bool &has_idr, std::vector &samples);
+ srs_error_t package_stap_a(SrsMediaPacket *msg, SrsRtpPacket *pkt);
+ srs_error_t package_nalus(SrsMediaPacket *msg, const std::vector &samples, std::vector &pkts);
+ srs_error_t package_single_nalu(SrsMediaPacket *msg, SrsNaluSample *sample, std::vector &pkts);
+ srs_error_t package_fu_a(SrsMediaPacket *msg, SrsNaluSample *sample, int fu_payload_size, std::vector &pkts);
srs_error_t consume_packets(std::vector &pkts);
};
diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp
index 4b99120a1..d2c27ff44 100644
--- a/trunk/src/app/srs_app_source.cpp
+++ b/trunk/src/app/srs_app_source.cpp
@@ -70,7 +70,7 @@ SrsRtmpJitter::~SrsRtmpJitter()
{
}
-srs_error_t SrsRtmpJitter::correct(SrsSharedPtrMessage *msg, SrsRtmpJitterAlgorithm ag)
+srs_error_t SrsRtmpJitter::correct(SrsMediaPacket *msg, SrsRtmpJitterAlgorithm ag)
{
srs_error_t err = srs_success;
@@ -140,7 +140,7 @@ SrsFastVector::SrsFastVector()
{
count = 0;
nb_msgs = 8;
- msgs = new SrsSharedPtrMessage *[nb_msgs];
+ msgs = new SrsMediaPacket *[nb_msgs];
}
SrsFastVector::~SrsFastVector()
@@ -164,12 +164,12 @@ int SrsFastVector::end()
return count;
}
-SrsSharedPtrMessage **SrsFastVector::data()
+SrsMediaPacket **SrsFastVector::data()
{
return msgs;
}
-SrsSharedPtrMessage *SrsFastVector::at(int index)
+SrsMediaPacket *SrsFastVector::at(int index)
{
srs_assert(index < count);
return msgs[index];
@@ -193,13 +193,13 @@ void SrsFastVector::erase(int _begin, int _end)
count -= _end - _begin;
}
-void SrsFastVector::push_back(SrsSharedPtrMessage *msg)
+void SrsFastVector::push_back(SrsMediaPacket *msg)
{
// increase vector.
if (count >= nb_msgs) {
int size = srs_max(SRS_PERF_MW_MSGS * 8, nb_msgs * 2);
- SrsSharedPtrMessage **buf = msgs;
- msgs = new SrsSharedPtrMessage *[size];
+ SrsMediaPacket **buf = msgs;
+ msgs = new SrsMediaPacket *[size];
for (int i = 0; i < nb_msgs; i++) {
msgs[i] = buf[i];
}
@@ -216,7 +216,7 @@ void SrsFastVector::push_back(SrsSharedPtrMessage *msg)
void SrsFastVector::free()
{
for (int i = 0; i < count; i++) {
- SrsSharedPtrMessage *msg = msgs[i];
+ SrsMediaPacket *msg = msgs[i];
srs_freep(msg);
}
count = 0;
@@ -250,7 +250,7 @@ void SrsMessageQueue::set_queue_size(srs_utime_t queue_size)
max_queue_size = queue_size;
}
-srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage *msg, bool *is_overflow)
+srs_error_t SrsMessageQueue::enqueue(SrsMediaPacket *msg, bool *is_overflow)
{
srs_error_t err = srs_success;
@@ -283,7 +283,7 @@ srs_error_t SrsMessageQueue::enqueue(SrsSharedPtrMessage *msg, bool *is_overflow
return err;
}
-srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsSharedPtrMessage **pmsgs, int &count)
+srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsMediaPacket **pmsgs, int &count)
{
srs_error_t err = srs_success;
@@ -295,10 +295,10 @@ srs_error_t SrsMessageQueue::dump_packets(int max_count, SrsSharedPtrMessage **p
srs_assert(max_count > 0);
count = srs_min(max_count, nb_msgs);
- SrsSharedPtrMessage **omsgs = msgs.data();
- memcpy(pmsgs, omsgs, count * sizeof(SrsSharedPtrMessage *));
+ SrsMediaPacket **omsgs = msgs.data();
+ memcpy(pmsgs, omsgs, count * sizeof(SrsMediaPacket *));
- SrsSharedPtrMessage *last = omsgs[count - 1];
+ SrsMediaPacket *last = omsgs[count - 1];
av_start_time = srs_utime_t(last->timestamp * SRS_UTIME_MILLISECONDS);
if (count >= nb_msgs) {
@@ -324,9 +324,9 @@ srs_error_t SrsMessageQueue::dump_packets(SrsLiveConsumer *consumer, bool atc, S
return err;
}
- SrsSharedPtrMessage **omsgs = msgs.data();
+ SrsMediaPacket **omsgs = msgs.data();
for (int i = 0; i < nb_msgs; i++) {
- SrsSharedPtrMessage *msg = omsgs[i];
+ SrsMediaPacket *msg = omsgs[i];
if ((err = consumer->enqueue(msg, atc, ag)) != srs_success) {
return srs_error_wrap(err, "consume message");
}
@@ -337,13 +337,13 @@ srs_error_t SrsMessageQueue::dump_packets(SrsLiveConsumer *consumer, bool atc, S
void SrsMessageQueue::shrink()
{
- SrsSharedPtrMessage *video_sh = NULL;
- SrsSharedPtrMessage *audio_sh = NULL;
+ SrsMediaPacket *video_sh = NULL;
+ SrsMediaPacket *audio_sh = NULL;
int msgs_size = (int)msgs.size();
// Remove all msgs, mark the sequence headers.
for (int i = 0; i < (int)msgs.size(); i++) {
- SrsSharedPtrMessage *msg = msgs.at(i);
+ SrsMediaPacket *msg = msgs.at(i);
if (msg->is_video() && SrsFlvVideo::sh(msg->payload(), msg->size())) {
srs_freep(video_sh);
@@ -380,10 +380,10 @@ void SrsMessageQueue::shrink()
void SrsMessageQueue::clear()
{
#ifndef SRS_PERF_QUEUE_FAST_VECTOR
- std::vector::iterator it;
+ std::vector::iterator it;
for (it = msgs.begin(); it != msgs.end(); ++it) {
- SrsSharedPtrMessage *msg = *it;
+ SrsMediaPacket *msg = *it;
srs_freep(msg);
}
#else
@@ -445,11 +445,11 @@ int64_t SrsLiveConsumer::get_time()
return jitter->get_time();
}
-srs_error_t SrsLiveConsumer::enqueue(SrsSharedPtrMessage *shared_msg, bool atc, SrsRtmpJitterAlgorithm ag)
+srs_error_t SrsLiveConsumer::enqueue(SrsMediaPacket *shared_msg, bool atc, SrsRtmpJitterAlgorithm ag)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *msg = shared_msg->copy();
+ SrsMediaPacket *msg = shared_msg->copy();
if (!atc) {
if ((err = jitter->correct(msg, ag)) != srs_success) {
@@ -606,7 +606,7 @@ bool SrsGopCache::enabled()
return enable_gop_cache;
}
-srs_error_t SrsGopCache::cache(SrsSharedPtrMessage *shared_msg)
+srs_error_t SrsGopCache::cache(SrsMediaPacket *shared_msg)
{
srs_error_t err = srs_success;
@@ -615,7 +615,7 @@ srs_error_t SrsGopCache::cache(SrsSharedPtrMessage *shared_msg)
}
// the gop cache know when to gop it.
- SrsSharedPtrMessage *msg = shared_msg;
+ SrsMediaPacket *msg = shared_msg;
// got video, update the video count if acceptable
if (msg->is_video()) {
@@ -669,9 +669,9 @@ srs_error_t SrsGopCache::cache(SrsSharedPtrMessage *shared_msg)
void SrsGopCache::clear()
{
- std::vector::iterator it;
+ std::vector::iterator it;
for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
- SrsSharedPtrMessage *msg = *it;
+ SrsMediaPacket *msg = *it;
srs_freep(msg);
}
gop_cache.clear();
@@ -684,9 +684,9 @@ srs_error_t SrsGopCache::dump(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitter
{
srs_error_t err = srs_success;
- std::vector::iterator it;
+ std::vector::iterator it;
for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
- SrsSharedPtrMessage *msg = *it;
+ SrsMediaPacket *msg = *it;
if ((err = consumer->enqueue(msg, atc, jitter_algorithm)) != srs_success) {
return srs_error_wrap(err, "enqueue message");
}
@@ -707,7 +707,7 @@ srs_utime_t SrsGopCache::start_time()
return 0;
}
- SrsSharedPtrMessage *msg = gop_cache[0];
+ SrsMediaPacket *msg = gop_cache[0];
srs_assert(msg);
return srs_utime_t(msg->timestamp * SRS_UTIME_MILLISECONDS);
@@ -727,7 +727,7 @@ ISrsLiveSourceHandler::~ISrsLiveSourceHandler()
}
// TODO: FIXME: Remove it?
-bool srs_hls_can_continue(int ret, SrsSharedPtrMessage *sh, SrsSharedPtrMessage *msg)
+bool srs_hls_can_continue(int ret, SrsMediaPacket *sh, SrsMediaPacket *msg)
{
// only continue for decode error.
if (ret != ERROR_HLS_DECODE_ERROR) {
@@ -758,9 +758,9 @@ SrsMixQueue::~SrsMixQueue()
void SrsMixQueue::clear()
{
- std::multimap::iterator it;
+ std::multimap::iterator it;
for (it = msgs.begin(); it != msgs.end(); ++it) {
- SrsSharedPtrMessage *msg = it->second;
+ SrsMediaPacket *msg = it->second;
srs_freep(msg);
}
msgs.clear();
@@ -769,7 +769,7 @@ void SrsMixQueue::clear()
nb_audios = 0;
}
-void SrsMixQueue::push(SrsSharedPtrMessage *msg)
+void SrsMixQueue::push(SrsMediaPacket *msg)
{
msgs.insert(std::make_pair(msg->timestamp, msg));
@@ -780,7 +780,7 @@ void SrsMixQueue::push(SrsSharedPtrMessage *msg)
}
}
-SrsSharedPtrMessage *SrsMixQueue::pop()
+SrsMediaPacket *SrsMixQueue::pop()
{
bool mix_ok = false;
@@ -804,8 +804,8 @@ SrsSharedPtrMessage *SrsMixQueue::pop()
}
// pop the first msg.
- std::multimap::iterator it = msgs.begin();
- SrsSharedPtrMessage *msg = it->second;
+ std::multimap::iterator it = msgs.begin();
+ SrsMediaPacket *msg = it->second;
msgs.erase(it);
if (msg->is_video()) {
@@ -920,7 +920,7 @@ srs_utime_t SrsOriginHub::cleanup_delay()
return srs_max(hls_delay, dash_delay);
}
-srs_error_t SrsOriginHub::on_meta_data(SrsSharedPtrMessage *shared_metadata, SrsOnMetaDataPacket *packet)
+srs_error_t SrsOriginHub::on_meta_data(SrsMediaPacket *shared_metadata, SrsOnMetaDataPacket *packet)
{
srs_error_t err = srs_success;
@@ -942,11 +942,11 @@ srs_error_t SrsOriginHub::on_meta_data(SrsSharedPtrMessage *shared_metadata, Srs
return err;
}
-srs_error_t SrsOriginHub::on_audio(SrsSharedPtrMessage *shared_audio)
+srs_error_t SrsOriginHub::on_audio(SrsMediaPacket *shared_audio)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *msg = shared_audio;
+ SrsMediaPacket *msg = shared_audio;
SrsRtmpFormat *format = source_->format_;
// Handle the metadata when got sequence header.
@@ -1028,11 +1028,11 @@ srs_error_t SrsOriginHub::on_audio(SrsSharedPtrMessage *shared_audio)
return err;
}
-srs_error_t SrsOriginHub::on_video(SrsSharedPtrMessage *shared_video, bool is_sequence_header)
+srs_error_t SrsOriginHub::on_video(SrsMediaPacket *shared_video, bool is_sequence_header)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *msg = shared_video;
+ SrsMediaPacket *msg = shared_video;
SrsRtmpFormat *format = source_->format_;
// cache the sequence header if h264
@@ -1186,9 +1186,9 @@ srs_error_t SrsOriginHub::on_forwarder_start(SrsForwarder *forwarder)
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *cache_metadata = source_->meta->data();
- SrsSharedPtrMessage *cache_sh_video = source_->meta->vsh();
- SrsSharedPtrMessage *cache_sh_audio = source_->meta->ash();
+ SrsMediaPacket *cache_metadata = source_->meta->data();
+ SrsMediaPacket *cache_sh_video = source_->meta->vsh();
+ SrsMediaPacket *cache_sh_audio = source_->meta->ash();
// feed the forwarder the metadata/sequence header,
// when reload to enable the forwarder.
@@ -1209,9 +1209,9 @@ srs_error_t SrsOriginHub::on_dvr_request_sh()
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *cache_metadata = source_->meta->data();
- SrsSharedPtrMessage *cache_sh_video = source_->meta->vsh();
- SrsSharedPtrMessage *cache_sh_audio = source_->meta->ash();
+ SrsMediaPacket *cache_metadata = source_->meta->data();
+ SrsMediaPacket *cache_sh_video = source_->meta->vsh();
+ SrsMediaPacket *cache_sh_audio = source_->meta->ash();
// feed the dvr the metadata/sequence header,
// when reload to start dvr, dvr will never get the sequence header in stream,
@@ -1239,14 +1239,14 @@ srs_error_t SrsOriginHub::on_hls_request_sh()
{
srs_error_t err = srs_success;
- SrsSharedPtrMessage *cache_sh_video = source_->meta->vsh();
+ SrsMediaPacket *cache_sh_video = source_->meta->vsh();
if (cache_sh_video) {
if ((err = hls->on_video(cache_sh_video, source_->meta->vsh_format())) != srs_success) {
return srs_error_wrap(err, "hls video");
}
}
- SrsSharedPtrMessage *cache_sh_audio = source_->meta->ash();
+ SrsMediaPacket *cache_sh_audio = source_->meta->ash();
if (cache_sh_audio) {
if ((err = hls->on_audio(cache_sh_audio, source_->meta->ash_format())) != srs_success) {
return srs_error_wrap(err, "hls audio");
@@ -1399,12 +1399,12 @@ void SrsMetaCache::clear()
srs_freep(audio);
}
-SrsSharedPtrMessage *SrsMetaCache::data()
+SrsMediaPacket *SrsMetaCache::data()
{
return meta;
}
-SrsSharedPtrMessage *SrsMetaCache::vsh()
+SrsMediaPacket *SrsMetaCache::vsh()
{
return video;
}
@@ -1414,7 +1414,7 @@ SrsFormat *SrsMetaCache::vsh_format()
return vformat;
}
-SrsSharedPtrMessage *SrsMetaCache::ash()
+SrsMediaPacket *SrsMetaCache::ash()
{
return audio;
}
@@ -1448,12 +1448,12 @@ srs_error_t SrsMetaCache::dumps(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitt
return err;
}
-SrsSharedPtrMessage *SrsMetaCache::previous_vsh()
+SrsMediaPacket *SrsMetaCache::previous_vsh()
{
return previous_video;
}
-SrsSharedPtrMessage *SrsMetaCache::previous_ash()
+SrsMediaPacket *SrsMetaCache::previous_ash()
{
return previous_audio;
}
@@ -1520,19 +1520,21 @@ srs_error_t SrsMetaCache::update_data(SrsMessageHeader *header, SrsOnMetaDataPac
// create a shared ptr message.
srs_freep(meta);
- meta = new SrsSharedPtrMessage();
+ meta = new SrsMediaPacket();
updated = true;
// dump message to shared ptr message.
// the payload/size managed by cache_metadata, user should not free it.
- if ((err = meta->create(header, payload, size)) != srs_success) {
+ SrsCommonMessage common_msg;
+ if ((err = common_msg.create(header, payload, size)) != srs_success) {
return srs_error_wrap(err, "create metadata");
}
+ common_msg.to_msg(meta);
return err;
}
-srs_error_t SrsMetaCache::update_ash(SrsSharedPtrMessage *msg)
+srs_error_t SrsMetaCache::update_ash(SrsMediaPacket *msg)
{
srs_freep(audio);
audio = msg->copy();
@@ -1540,7 +1542,7 @@ srs_error_t SrsMetaCache::update_ash(SrsSharedPtrMessage *msg)
return aformat->on_audio(msg);
}
-srs_error_t SrsMetaCache::update_vsh(SrsSharedPtrMessage *msg)
+srs_error_t SrsMetaCache::update_vsh(SrsMediaPacket *msg)
{
srs_freep(video);
video = msg->copy();
@@ -1962,7 +1964,6 @@ srs_error_t SrsLiveSource::on_meta_data(SrsCommonMessage *msg, SrsOnMetaDataPack
srs_error_t SrsLiveSource::on_audio(SrsCommonMessage *shared_audio)
{
- srs_error_t err = srs_success;
// Detect where stream is monotonically increasing.
if (!mix_correct && is_monotonically_increase) {
@@ -1976,15 +1977,13 @@ srs_error_t SrsLiveSource::on_audio(SrsCommonMessage *shared_audio)
// convert shared_audio to msg, user should not use shared_audio again.
// the payload is transfer to msg, and set to NULL in shared_audio.
- SrsSharedPtrMessage msg;
- if ((err = msg.create(shared_audio)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ shared_audio->to_msg(&msg);
return on_frame(&msg);
}
-srs_error_t SrsLiveSource::on_frame(SrsSharedPtrMessage *msg)
+srs_error_t SrsLiveSource::on_frame(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -2001,7 +2000,7 @@ srs_error_t SrsLiveSource::on_frame(SrsSharedPtrMessage *msg)
mix_queue->push(msg->copy());
// fetch someone from mix queue.
- SrsSharedPtrMessage *m = mix_queue->pop();
+ SrsMediaPacket *m = mix_queue->pop();
if (!m) {
return err;
}
@@ -2017,7 +2016,7 @@ srs_error_t SrsLiveSource::on_frame(SrsSharedPtrMessage *msg)
return err;
}
-srs_error_t SrsLiveSource::on_audio_imp(SrsSharedPtrMessage *msg)
+srs_error_t SrsLiveSource::on_audio_imp(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -2122,15 +2121,13 @@ srs_error_t SrsLiveSource::on_video(SrsCommonMessage *shared_video)
// convert shared_video to msg, user should not use shared_video again.
// the payload is transfer to msg, and set to NULL in shared_video.
- SrsSharedPtrMessage msg;
- if ((err = msg.create(shared_video)) != srs_success) {
- return srs_error_wrap(err, "create message");
- }
+ SrsMediaPacket msg;
+ shared_video->to_msg(&msg);
return on_frame(&msg);
}
-srs_error_t SrsLiveSource::on_video_imp(SrsSharedPtrMessage *msg)
+srs_error_t SrsLiveSource::on_video_imp(SrsMediaPacket *msg)
{
srs_error_t err = srs_success;
@@ -2271,7 +2268,6 @@ srs_error_t SrsLiveSource::on_aggregate(SrsCommonMessage *msg)
o.header.timestamp_delta = timestamp;
o.header.timestamp = timestamp;
o.header.stream_id = stream_id;
- o.header.prefer_cid = msg->header.prefer_cid;
if (data_size > 0) {
o.create_payload(data_size);
diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp
index 6ce12e9ad..26f699b16 100644
--- a/trunk/src/app/srs_app_source.hpp
+++ b/trunk/src/app/srs_app_source.hpp
@@ -29,7 +29,7 @@ class SrsPublishEdge;
class SrsLiveSource;
class SrsCommonMessage;
class SrsOnMetaDataPacket;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsForwarder;
class ISrsRequest;
class SrsStSocket;
@@ -73,7 +73,7 @@ public:
public:
// detect the time jitter and correct it.
// @param ag the algorithm to use for time jitter.
- virtual srs_error_t correct(SrsSharedPtrMessage *msg, SrsRtmpJitterAlgorithm ag);
+ virtual srs_error_t correct(SrsMediaPacket *msg, SrsRtmpJitterAlgorithm ag);
// Get current client time, the last packet time.
virtual int64_t get_time();
};
@@ -83,7 +83,7 @@ public:
class SrsFastVector
{
private:
- SrsSharedPtrMessage **msgs;
+ SrsMediaPacket **msgs;
int nb_msgs;
int count;
@@ -95,11 +95,11 @@ public:
virtual int size();
virtual int begin();
virtual int end();
- virtual SrsSharedPtrMessage **data();
- virtual SrsSharedPtrMessage *at(int index);
+ virtual SrsMediaPacket **data();
+ virtual SrsMediaPacket *at(int index);
virtual void clear();
virtual void erase(int _begin, int _end);
- virtual void push_back(SrsSharedPtrMessage *msg);
+ virtual void push_back(SrsMediaPacket *msg);
virtual void free();
};
#endif
@@ -121,7 +121,7 @@ private:
#ifdef SRS_PERF_QUEUE_FAST_VECTOR
SrsFastVector msgs;
#else
- std::vector msgs;
+ std::vector msgs;
#endif
public:
SrsMessageQueue(bool ignore_shrink = false);
@@ -140,12 +140,12 @@ public:
// Enqueue the message, the timestamp always monotonically.
// @param msg, the msg to enqueue, user never free it whatever the return code.
// @param is_overflow, whether overflow and shrinked. NULL to ignore.
- virtual srs_error_t enqueue(SrsSharedPtrMessage *msg, bool *is_overflow = NULL);
+ virtual srs_error_t enqueue(SrsMediaPacket *msg, bool *is_overflow = NULL);
// Get packets in consumer queue.
- // @pmsgs SrsSharedPtrMessage*[], used to store the msgs, user must alloc it.
+ // @pmsgs SrsMediaPacket*[], used to store the msgs, user must alloc it.
// @count the count in array, output param.
// @max_count the max count to dequeue, must be positive.
- virtual srs_error_t dump_packets(int max_count, SrsSharedPtrMessage **pmsgs, int &count);
+ virtual srs_error_t dump_packets(int max_count, SrsMediaPacket **pmsgs, int &count);
// Dumps packets to consumer, use specified args.
// @remark the atc/tba/tbv/ag are same to SrsLiveConsumer.enqueue().
virtual srs_error_t dump_packets(SrsLiveConsumer *consumer, bool atc, SrsRtmpJitterAlgorithm ag);
@@ -212,7 +212,7 @@ public:
// @param shared_msg, directly ptr, copy it if need to save it.
// @param whether atc, donot use jitter correct if true.
// @param ag the algorithm of time jitter.
- virtual srs_error_t enqueue(SrsSharedPtrMessage *shared_msg, bool atc, SrsRtmpJitterAlgorithm ag);
+ virtual srs_error_t enqueue(SrsMediaPacket *shared_msg, bool atc, SrsRtmpJitterAlgorithm ag);
// Get packets in consumer queue.
// @param msgs the msgs array to dump packets to send.
// @param count the count in array, intput and output param.
@@ -262,7 +262,7 @@ private:
// @see: https://github.com/ossrs/srs/issues/124
int audio_after_last_video_count;
// cached gop.
- std::vector gop_cache;
+ std::vector gop_cache;
public:
SrsGopCache();
@@ -279,7 +279,7 @@ public:
// 1. cache the gop when got h264 video packet.
// 2. clear gop when got keyframe.
// @param shared_msg, directly ptr, copy it if need to save it.
- virtual srs_error_t cache(SrsSharedPtrMessage *shared_msg);
+ virtual srs_error_t cache(SrsMediaPacket *shared_msg);
// clear the gop cache.
virtual void clear();
// dump the cached gop to consumer.
@@ -317,7 +317,7 @@ class SrsMixQueue
private:
uint32_t nb_videos;
uint32_t nb_audios;
- std::multimap msgs;
+ std::multimap msgs;
public:
SrsMixQueue();
@@ -325,8 +325,8 @@ public:
public:
virtual void clear();
- virtual void push(SrsSharedPtrMessage *msg);
- virtual SrsSharedPtrMessage *pop();
+ virtual void push(SrsMediaPacket *msg);
+ virtual SrsMediaPacket *pop();
};
// The hub for origin is a collection of utilities for origin only,
@@ -381,11 +381,11 @@ public:
public:
// When got a parsed metadata.
- virtual srs_error_t on_meta_data(SrsSharedPtrMessage *shared_metadata, SrsOnMetaDataPacket *packet);
+ virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata, SrsOnMetaDataPacket *packet);
// When got a parsed audio packet.
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio);
// When got a parsed video packet.
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, bool is_sequence_header);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video, bool is_sequence_header);
public:
// When start publish stream.
@@ -413,13 +413,13 @@ class SrsMetaCache
{
private:
// The cached metadata, FLV script data tag.
- SrsSharedPtrMessage *meta;
+ SrsMediaPacket *meta;
// The cached video sequence header, for example, sps/pps for h.264.
- SrsSharedPtrMessage *video;
- SrsSharedPtrMessage *previous_video;
+ SrsMediaPacket *video;
+ SrsMediaPacket *previous_video;
// The cached audio sequence header, for example, asc for aac.
- SrsSharedPtrMessage *audio;
- SrsSharedPtrMessage *previous_audio;
+ SrsMediaPacket *audio;
+ SrsMediaPacket *previous_audio;
// The format for sequence header.
SrsRtmpFormat *vformat;
SrsRtmpFormat *aformat;
@@ -436,12 +436,12 @@ public:
public:
// Get the cached metadata.
- virtual SrsSharedPtrMessage *data();
+ virtual SrsMediaPacket *data();
// Get the cached vsh(video sequence header).
- virtual SrsSharedPtrMessage *vsh();
+ virtual SrsMediaPacket *vsh();
virtual SrsFormat *vsh_format();
// Get the cached ash(audio sequence header).
- virtual SrsSharedPtrMessage *ash();
+ virtual SrsMediaPacket *ash();
virtual SrsFormat *ash_format();
// Dumps cached metadata to consumer.
// @param dm Whether dumps the metadata.
@@ -450,8 +450,8 @@ public:
public:
// Previous exists sequence header.
- virtual SrsSharedPtrMessage *previous_vsh();
- virtual SrsSharedPtrMessage *previous_ash();
+ virtual SrsMediaPacket *previous_vsh();
+ virtual SrsMediaPacket *previous_ash();
// Update previous sequence header, drop old one, set to new sequence header.
virtual void update_previous_vsh();
virtual void update_previous_ash();
@@ -460,9 +460,9 @@ public:
// Update the cached metadata by packet.
virtual srs_error_t update_data(SrsMessageHeader *header, SrsOnMetaDataPacket *metadata, bool &updated);
// Update the cached audio sequence header.
- virtual srs_error_t update_ash(SrsSharedPtrMessage *msg);
+ virtual srs_error_t update_ash(SrsMediaPacket *msg);
// Update the cached video sequence header.
- virtual srs_error_t update_vsh(SrsSharedPtrMessage *msg);
+ virtual srs_error_t update_vsh(SrsMediaPacket *msg);
};
// The source manager to create and refresh all stream sources.
@@ -595,19 +595,19 @@ public:
virtual srs_error_t on_meta_data(SrsCommonMessage *msg, SrsOnMetaDataPacket *metadata);
public:
- // TODO: FIXME: Use SrsSharedPtrMessage instead.
+ // TODO: FIXME: Use SrsMediaPacket instead.
virtual srs_error_t on_audio(SrsCommonMessage *audio);
- srs_error_t on_frame(SrsSharedPtrMessage *msg);
+ srs_error_t on_frame(SrsMediaPacket *msg);
private:
- virtual srs_error_t on_audio_imp(SrsSharedPtrMessage *audio);
+ virtual srs_error_t on_audio_imp(SrsMediaPacket *audio);
public:
- // TODO: FIXME: Use SrsSharedPtrMessage instead.
+ // TODO: FIXME: Use SrsMediaPacket instead.
virtual srs_error_t on_video(SrsCommonMessage *video);
private:
- virtual srs_error_t on_video_imp(SrsSharedPtrMessage *video);
+ virtual srs_error_t on_video_imp(SrsMediaPacket *video);
public:
virtual srs_error_t on_aggregate(SrsCommonMessage *msg);
diff --git a/trunk/src/app/srs_app_srt_source.cpp b/trunk/src/app/srs_app_srt_source.cpp
index e9e1c6c5c..d9abf9f97 100644
--- a/trunk/src/app/srs_app_srt_source.cpp
+++ b/trunk/src/app/srs_app_srt_source.cpp
@@ -46,7 +46,7 @@ char *SrsSrtPacket::wrap(int size)
// Create a large enough message, with under-layer buffer.
srs_freep(shared_buffer_);
- shared_buffer_ = new SrsSharedPtrMessage();
+ shared_buffer_ = new SrsMediaPacket();
char *buf = new char[size];
shared_buffer_->wrap(buf, size);
@@ -61,7 +61,7 @@ char *SrsSrtPacket::wrap(char *data, int size)
return buf;
}
-char *SrsSrtPacket::wrap(SrsSharedPtrMessage *msg)
+char *SrsSrtPacket::wrap(SrsMediaPacket *msg)
{
// Generally, the wrap(msg) is used for RTMP to SRT, where the msg
// is not generated by SRT.
@@ -79,7 +79,7 @@ SrsSrtPacket *SrsSrtPacket::copy()
{
SrsSrtPacket *cp = new SrsSrtPacket();
- cp->shared_buffer_ = shared_buffer_ ? shared_buffer_->copy2() : NULL;
+ cp->shared_buffer_ = shared_buffer_ ? shared_buffer_->copy() : NULL;
cp->actual_buffer_size_ = actual_buffer_size_;
return cp;
@@ -507,10 +507,8 @@ srs_error_t SrsSrtFrameBuilder::check_sps_pps_change(SrsTsMessage *msg)
return srs_error_wrap(err, "create rtmp");
}
- SrsSharedPtrMessage frame;
- if ((err = frame.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create frame");
- }
+ SrsMediaPacket frame;
+ rtmp.to_msg(&frame);
if ((err = bridge_->on_frame(&frame)) != srs_success) {
return srs_error_wrap(err, "srt to rtmp sps/pps");
@@ -567,10 +565,8 @@ srs_error_t SrsSrtFrameBuilder::on_h264_frame(SrsTsMessage *msg, vectoron_frame(&frame)) != srs_success) {
return srs_error_wrap(err, "srt ts video to rtmp");
@@ -697,10 +693,8 @@ srs_error_t SrsSrtFrameBuilder::check_vps_sps_pps_change(SrsTsMessage *msg)
return srs_error_wrap(err, "create rtmp");
}
- SrsSharedPtrMessage frame;
- if ((err = frame.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create frame");
- }
+ SrsMediaPacket frame;
+ rtmp.to_msg(&frame);
if ((err = bridge_->on_frame(&frame)) != srs_success) {
return srs_error_wrap(err, "srt to rtmp vps/sps/pps");
@@ -764,10 +758,8 @@ srs_error_t SrsSrtFrameBuilder::on_hevc_frame(SrsTsMessage *msg, vectoron_frame(&frame)) != srs_success) {
return srs_error_wrap(err, "srt ts hevc video to rtmp");
@@ -880,10 +872,8 @@ srs_error_t SrsSrtFrameBuilder::check_audio_sh_change(SrsTsMessage *msg, uint32_
stream.write_1bytes(0);
stream.write_bytes((char *)audio_sh_.data(), audio_sh_.size());
- SrsSharedPtrMessage frame;
- if ((err = frame.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create frame");
- }
+ SrsMediaPacket frame;
+ rtmp.to_msg(&frame);
if ((err = bridge_->on_frame(&frame)) != srs_success) {
return srs_error_wrap(err, "srt to rtmp audio sh");
@@ -910,10 +900,8 @@ srs_error_t SrsSrtFrameBuilder::on_aac_frame(SrsTsMessage *msg, uint32_t pts, ch
// Write audio frame.
stream.write_bytes(data, data_size);
- SrsSharedPtrMessage frame;
- if ((err = frame.create(&rtmp)) != srs_success) {
- return srs_error_wrap(err, "create frame");
- }
+ SrsMediaPacket frame;
+ rtmp.to_msg(&frame);
if ((err = bridge_->on_frame(&frame)) != srs_success) {
return srs_error_wrap(err, "srt to rtmp audio sh");
diff --git a/trunk/src/app/srs_app_srt_source.hpp b/trunk/src/app/srs_app_srt_source.hpp
index 25c4b5ee1..63774f065 100644
--- a/trunk/src/app/srs_app_srt_source.hpp
+++ b/trunk/src/app/srs_app_srt_source.hpp
@@ -18,7 +18,7 @@
#include
#include
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class ISrsRequest;
class SrsLiveSource;
class SrsSrtSource;
@@ -37,7 +37,7 @@ public:
char *wrap(int size);
char *wrap(char *data, int size);
// Wrap the shared message, we copy it.
- char *wrap(SrsSharedPtrMessage *msg);
+ char *wrap(SrsMediaPacket *msg);
// Copy the SRT packet.
virtual SrsSrtPacket *copy();
@@ -46,7 +46,7 @@ public:
int size();
private:
- SrsSharedPtrMessage *shared_buffer_;
+ SrsMediaPacket *shared_buffer_;
// The size of SRT packet or SRT payload.
int actual_buffer_size_;
};
diff --git a/trunk/src/app/srs_app_stream_bridge.cpp b/trunk/src/app/srs_app_stream_bridge.cpp
index 0b4d39ebd..20423c5e2 100644
--- a/trunk/src/app/srs_app_stream_bridge.cpp
+++ b/trunk/src/app/srs_app_stream_bridge.cpp
@@ -60,7 +60,7 @@ void SrsFrameToRtmpBridge::on_unpublish()
source_->on_unpublish();
}
-srs_error_t SrsFrameToRtmpBridge::on_frame(SrsSharedPtrMessage *frame)
+srs_error_t SrsFrameToRtmpBridge::on_frame(SrsMediaPacket *frame)
{
return source_->on_frame(frame);
}
@@ -120,7 +120,7 @@ void SrsFrameToRtcBridge::on_unpublish()
source_->on_unpublish();
}
-srs_error_t SrsFrameToRtcBridge::on_frame(SrsSharedPtrMessage *frame)
+srs_error_t SrsFrameToRtcBridge::on_frame(SrsMediaPacket *frame)
{
#ifdef SRS_FFMPEG_FIT
return rtp_builder_->on_frame(frame);
@@ -178,7 +178,7 @@ void SrsFrameToRtspBridge::on_unpublish()
source_->on_unpublish();
}
-srs_error_t SrsFrameToRtspBridge::on_frame(SrsSharedPtrMessage *frame)
+srs_error_t SrsFrameToRtspBridge::on_frame(SrsMediaPacket *frame)
{
return rtp_builder_->on_frame(frame);
}
@@ -237,7 +237,7 @@ void SrsCompositeBridge::on_unpublish()
}
}
-srs_error_t SrsCompositeBridge::on_frame(SrsSharedPtrMessage *frame)
+srs_error_t SrsCompositeBridge::on_frame(SrsMediaPacket *frame)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_stream_bridge.hpp b/trunk/src/app/srs_app_stream_bridge.hpp
index 143a08566..b3aa26735 100644
--- a/trunk/src/app/srs_app_stream_bridge.hpp
+++ b/trunk/src/app/srs_app_stream_bridge.hpp
@@ -15,7 +15,7 @@
#include
class ISrsRequest;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
class SrsLiveSource;
class SrsRtcSource;
class SrsRtmpFormat;
@@ -37,7 +37,7 @@ public:
public:
virtual srs_error_t initialize(ISrsRequest *r) = 0;
virtual srs_error_t on_publish() = 0;
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame) = 0;
+ virtual srs_error_t on_frame(SrsMediaPacket *frame) = 0;
virtual void on_unpublish() = 0;
};
@@ -59,7 +59,7 @@ public:
virtual void on_unpublish();
public:
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
+ virtual srs_error_t on_frame(SrsMediaPacket *frame);
};
// A bridge to covert AV frame to WebRTC stream.
@@ -80,7 +80,7 @@ public:
virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
+ virtual srs_error_t on_frame(SrsMediaPacket *frame);
srs_error_t on_rtp(SrsRtpPacket *pkt);
};
@@ -102,7 +102,7 @@ public:
virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
+ virtual srs_error_t on_frame(SrsMediaPacket *frame);
srs_error_t on_rtp(SrsRtpPacket *pkt);
};
#endif
@@ -124,7 +124,7 @@ public:
virtual void on_unpublish();
public:
- virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
+ virtual srs_error_t on_frame(SrsMediaPacket *frame);
public:
SrsCompositeBridge *append(ISrsStreamBridge *bridge);
diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp
index cbd70bbab..a76ba6b5e 100644
--- a/trunk/src/core/srs_core_version7.hpp
+++ b/trunk/src/core/srs_core_version7.hpp
@@ -9,6 +9,6 @@
#define VERSION_MAJOR 7
#define VERSION_MINOR 0
-#define VERSION_REVISION 73
+#define VERSION_REVISION 74
#endif
\ No newline at end of file
diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp
index 05194cac9..dead7d652 100644
--- a/trunk/src/kernel/srs_kernel_codec.cpp
+++ b/trunk/src/kernel/srs_kernel_codec.cpp
@@ -14,6 +14,7 @@ using namespace std;
#include
#include
#include
+#include
#include
#include
#include
@@ -715,30 +716,6 @@ string srs_hevc_level2str(SrsHevcLevel level)
}
}
-SrsSample::SrsSample()
-{
- size = 0;
- bytes = NULL;
-}
-
-SrsSample::SrsSample(char *b, int s)
-{
- size = s;
- bytes = b;
-}
-
-SrsSample::~SrsSample()
-{
-}
-
-SrsSample *SrsSample::copy()
-{
- SrsSample *p = new SrsSample();
- p->bytes = bytes;
- p->size = size;
- return p;
-}
-
SrsCodecConfig::SrsCodecConfig()
{
}
@@ -795,2354 +772,6 @@ bool SrsVideoCodecConfig::is_avc_codec_ok()
return !avc_extra_data.empty();
}
-SrsFrame::SrsFrame()
-{
- codec = NULL;
- nb_samples = 0;
- dts = 0;
- cts = 0;
-}
-
-SrsFrame::~SrsFrame()
-{
-}
-
-srs_error_t SrsFrame::initialize(SrsCodecConfig *c)
-{
- codec = c;
- nb_samples = 0;
- dts = 0;
- cts = 0;
- return srs_success;
-}
-
-srs_error_t SrsFrame::add_sample(char *bytes, int size)
-{
- srs_error_t err = srs_success;
-
- // Ignore empty sample.
- if (!bytes || size <= 0)
- return err;
-
- if (nb_samples >= SrsMaxNbSamples) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "Frame samples overflow");
- }
-
- SrsSample *sample = &samples[nb_samples++];
- sample->bytes = bytes;
- sample->size = size;
-
- return err;
-}
-
-SrsAudioFrame::SrsAudioFrame()
-{
- aac_packet_type = SrsAudioAacFrameTraitForbidden;
-}
-
-SrsAudioFrame::~SrsAudioFrame()
-{
-}
-
-SrsAudioCodecConfig *SrsAudioFrame::acodec()
-{
- return (SrsAudioCodecConfig *)codec;
-}
-
-SrsVideoFrame::SrsVideoFrame()
-{
- frame_type = SrsVideoAvcFrameTypeForbidden;
- avc_packet_type = SrsVideoAvcFrameTraitForbidden;
- has_idr = has_aud = has_sps_pps = false;
- first_nalu_type = SrsAvcNaluTypeForbidden;
-}
-
-SrsVideoFrame::~SrsVideoFrame()
-{
-}
-
-srs_error_t SrsVideoFrame::initialize(SrsCodecConfig *c)
-{
- first_nalu_type = SrsAvcNaluTypeForbidden;
- has_idr = has_sps_pps = has_aud = false;
- return SrsFrame::initialize(c);
-}
-
-srs_error_t SrsVideoFrame::add_sample(char *bytes, int size)
-{
- srs_error_t err = srs_success;
-
- if ((err = SrsFrame::add_sample(bytes, size)) != srs_success) {
- return srs_error_wrap(err, "add frame");
- }
-
- SrsVideoCodecConfig *c = vcodec();
- if (!bytes || size <= 0)
- return err;
-
- // For HEVC(H.265), try to parse the IDR from NALUs.
- if (c && c->id == SrsVideoCodecIdHEVC) {
- SrsHevcNaluType nalu_type = SrsHevcNaluTypeParse(bytes[0]);
- has_idr = SrsIsIRAP(nalu_type);
- return err;
- }
-
- // By default, use AVC(H.264) to parse NALU.
- // For video, parse the nalu type, set the IDR flag.
- SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(bytes[0]);
-
- if (nal_unit_type == SrsAvcNaluTypeIDR) {
- has_idr = true;
- } else if (nal_unit_type == SrsAvcNaluTypeSPS || nal_unit_type == SrsAvcNaluTypePPS) {
- has_sps_pps = true;
- } else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) {
- has_aud = true;
- }
-
- if (first_nalu_type == SrsAvcNaluTypeReserved) {
- first_nalu_type = nal_unit_type;
- }
-
- return err;
-}
-
-SrsVideoCodecConfig *SrsVideoFrame::vcodec()
-{
- return (SrsVideoCodecConfig *)codec;
-}
-
-srs_error_t SrsVideoFrame::parse_avc_nalu_type(const SrsSample *sample, SrsAvcNaluType &avc_nalu_type)
-{
- srs_error_t err = srs_success;
-
- if (sample == NULL || sample->size < 1) {
- return srs_error_new(ERROR_NALU_EMPTY, "empty nalu");
- }
-
- uint8_t header = sample->bytes[0];
- avc_nalu_type = SrsAvcNaluTypeParse(header);
-
- return err;
-}
-
-srs_error_t SrsVideoFrame::parse_avc_bframe(const SrsSample *sample, bool &is_b_frame)
-{
- srs_error_t err = srs_success;
-
- SrsAvcNaluType nalu_type;
- if ((err = parse_avc_nalu_type(sample, nalu_type)) != srs_success) {
- return srs_error_wrap(err, "parse avc nalu type error");
- }
-
- if (nalu_type != SrsAvcNaluTypeNonIDR && nalu_type != SrsAvcNaluTypeDataPartitionA && nalu_type != SrsAvcNaluTypeDataPartitionB && nalu_type != SrsAvcNaluTypeDataPartitionC) {
- is_b_frame = false;
- return err;
- }
-
- SrsUniquePtr stream(new SrsBuffer(sample->bytes, sample->size));
-
- // Skip nalu header.
- stream->skip(1);
-
- SrsBitBuffer bitstream(stream.get());
- int32_t first_mb_in_slice = 0;
- if ((err = srs_avc_nalu_read_uev(&bitstream, first_mb_in_slice)) != srs_success) {
- return srs_error_wrap(err, "nalu read uev");
- }
-
- int32_t slice_type_v = 0;
- if ((err = srs_avc_nalu_read_uev(&bitstream, slice_type_v)) != srs_success) {
- return srs_error_wrap(err, "nalu read uev");
- }
- SrsAvcSliceType slice_type = (SrsAvcSliceType)slice_type_v;
-
- is_b_frame = slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1;
- if (is_b_frame) {
- srs_verbose("nalu_type=%d, slice type=%d", nalu_type, slice_type);
- }
-
- return err;
-}
-
-srs_error_t SrsVideoFrame::parse_hevc_nalu_type(const SrsSample *sample, SrsHevcNaluType &hevc_nalu_type)
-{
- srs_error_t err = srs_success;
-
- if (sample == NULL || sample->size < 1) {
- return srs_error_new(ERROR_NALU_EMPTY, "empty hevc nalu");
- }
-
- uint8_t header = sample->bytes[0];
- hevc_nalu_type = SrsHevcNaluTypeParse(header);
-
- return err;
-}
-
-srs_error_t SrsVideoFrame::parse_hevc_bframe(const SrsSample *sample, SrsFormat *format, bool &is_b_frame)
-{
- srs_error_t err = srs_success;
-
- SrsHevcNaluType nalu_type;
- if ((err = parse_hevc_nalu_type(sample, nalu_type)) != srs_success) {
- return srs_error_wrap(err, "parse hevc nalu type error");
- }
-
- if (nalu_type > SrsHevcNaluType_CODED_SLICE_TFD) {
- is_b_frame = false;
- return err;
- }
-
- SrsUniquePtr stream(new SrsBuffer(sample->bytes, sample->size));
- stream->skip(2);
-
- // @see 7.3.6.1 General slice segment header syntax
- // @doc ITU-T-H.265-2021.pdf, page 66.
- SrsBitBuffer bs(stream.get());
-
- uint8_t first_slice_segment_in_pic_flag = bs.read_bit();
-
- uint32_t slice_pic_parameter_set_id;
- if ((err = bs.read_bits_ue(slice_pic_parameter_set_id)) != srs_success) {
- return srs_error_wrap(err, "read slice pic parameter set id");
- }
-
- if (slice_pic_parameter_set_id >= SrsHevcMax_PPS_COUNT) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "slice pic parameter set id out of range: %d", slice_pic_parameter_set_id);
- }
-
- SrsHevcRbspPps *pps = &(format->vcodec->hevc_dec_conf_record_.pps_table[slice_pic_parameter_set_id]);
- if (!pps) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps not found");
- }
-
- uint8_t dependent_slice_segment_flag = 0;
- if (!first_slice_segment_in_pic_flag) {
- if (pps->dependent_slice_segments_enabled_flag) {
- dependent_slice_segment_flag = bs.read_bit();
- }
- }
-
- if (dependent_slice_segment_flag) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "dependent slice segment flag is not supported");
- }
-
- for (int i = 0; i < pps->num_extra_slice_header_bits; i++) {
- bs.skip_bits(1);
- }
-
- uint32_t slice_type;
- if ((err = bs.read_bits_ue(slice_type)) != srs_success) {
- return srs_error_wrap(err, "read slice type");
- }
-
- is_b_frame = slice_type == SrsHevcSliceTypeB;
- if (is_b_frame) {
- srs_verbose("nalu_type=%d, slice type=%d", nalu_type, slice_type);
- }
-
- // no need to evaluate the rest
-
- return err;
-}
-
-SrsFormat::SrsFormat()
-{
- acodec = NULL;
- vcodec = NULL;
- audio = NULL;
- video = NULL;
- avc_parse_sps = true;
- try_annexb_first = true;
- raw = NULL;
- nb_raw = 0;
-}
-
-SrsFormat::~SrsFormat()
-{
- srs_freep(audio);
- srs_freep(video);
- srs_freep(acodec);
- srs_freep(vcodec);
-}
-
-// CRITICAL: This method is called AFTER the source has been added to the source pool
-// in the fetch_or_create pattern (see PR 4449).
-//
-// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
-// This prevents the race condition where multiple coroutines could create duplicate sources
-// for the same stream when context switches occurred during initialization.
-srs_error_t SrsFormat::initialize()
-{
- if (!vcodec) {
- vcodec = new SrsVideoCodecConfig();
- }
-
- return srs_success;
-}
-
-srs_error_t SrsFormat::on_audio(int64_t timestamp, char *data, int size)
-{
- srs_error_t err = srs_success;
-
- if (!data || size <= 0) {
- srs_info("no audio present, ignore it.");
- return err;
- }
-
- SrsUniquePtr buffer(new SrsBuffer(data, size));
-
- // We already checked the size is positive and data is not NULL.
- srs_assert(buffer->require(1));
-
- // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
- uint8_t v = buffer->read_1bytes();
- SrsAudioCodecId codec = (SrsAudioCodecId)((v >> 4) & 0x0f);
-
- if (codec != SrsAudioCodecIdMP3 && codec != SrsAudioCodecIdAAC && codec != SrsAudioCodecIdOpus) {
- return err;
- }
-
- bool fresh = !acodec;
- if (!acodec) {
- acodec = new SrsAudioCodecConfig();
- }
- if (!audio) {
- audio = new SrsAudioFrame();
- }
-
- if ((err = audio->initialize(acodec)) != srs_success) {
- return srs_error_wrap(err, "init audio");
- }
-
- // Parse by specified codec.
- buffer->skip(-1 * buffer->pos());
-
- if (codec == SrsAudioCodecIdMP3) {
- return audio_mp3_demux(buffer.get(), timestamp, fresh);
- } else if (codec == SrsAudioCodecIdAAC) {
- return audio_aac_demux(buffer.get(), timestamp);
- } else {
- return srs_error_new(ERROR_NOT_IMPLEMENTED, "opus demuxer not implemented");
- }
-}
-
-srs_error_t SrsFormat::on_video(int64_t timestamp, char *data, int size)
-{
- srs_error_t err = srs_success;
-
- if (!data || size <= 0) {
- srs_trace("no video present, ignore it.");
- return err;
- }
-
- SrsUniquePtr buffer(new SrsBuffer(data, size));
- return video_avc_demux(buffer.get(), timestamp);
-}
-
-srs_error_t SrsFormat::on_aac_sequence_header(char *data, int size)
-{
- srs_error_t err = srs_success;
-
- if (!acodec) {
- acodec = new SrsAudioCodecConfig();
- }
- if (!audio) {
- audio = new SrsAudioFrame();
- }
-
- if ((err = audio->initialize(acodec)) != srs_success) {
- return srs_error_wrap(err, "init audio");
- }
-
- return audio_aac_sequence_header_demux(data, size);
-}
-
-bool SrsFormat::is_aac_sequence_header()
-{
- return acodec && acodec->id == SrsAudioCodecIdAAC && audio && audio->aac_packet_type == SrsAudioAacFrameTraitSequenceHeader;
-}
-
-bool SrsFormat::is_mp3_sequence_header()
-{
- return acodec && acodec->id == SrsAudioCodecIdMP3 && audio && audio->aac_packet_type == SrsAudioMp3FrameTraitSequenceHeader;
-}
-
-bool SrsFormat::is_avc_sequence_header()
-{
- bool h264 = (vcodec && vcodec->id == SrsVideoCodecIdAVC);
- bool h265 = (vcodec && vcodec->id == SrsVideoCodecIdHEVC);
- bool av1 = (vcodec && vcodec->id == SrsVideoCodecIdAV1);
- return vcodec && (h264 || h265 || av1) && video && video->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader;
-}
-
-// Remove the emulation bytes from stream, and return num of bytes of the rbsp.
-int srs_rbsp_remove_emulation_bytes(SrsBuffer *stream, std::vector &rbsp)
-{
- int nb_rbsp = 0;
- while (!stream->empty()) {
- rbsp[nb_rbsp] = stream->read_1bytes();
-
- // .. 00 00 03 xx, the 03 byte should be drop where xx represents any
- // 2 bit pattern: 00, 01, 10, or 11.
- if (nb_rbsp >= 2 && rbsp[nb_rbsp - 2] == 0 && rbsp[nb_rbsp - 1] == 0 && rbsp[nb_rbsp] == 3) {
- // read 1byte more.
- if (stream->empty()) {
- nb_rbsp++;
- break;
- }
-
- // |---------------------|----------------------------|
- // | rbsp | nalu with emulation bytes |
- // |---------------------|----------------------------|
- // | 0x00 0x00 0x00 | 0x00 0x00 0x03 0x00 |
- // | 0x00 0x00 0x01 | 0x00 0x00 0x03 0x01 |
- // | 0x00 0x00 0x02 | 0x00 0x00 0x03 0x02 |
- // | 0x00 0x00 0x03 | 0x00 0x00 0x03 0x03 |
- // | 0x00 0x00 0x03 0x04 | 0x00 0x00 0x03 0x04 |
- // |---------------------|----------------------------|
- uint8_t ev = stream->read_1bytes();
- if (ev > 3) {
- nb_rbsp++;
- }
- rbsp[nb_rbsp] = ev;
- }
-
- nb_rbsp++;
- }
-
- return nb_rbsp;
-}
-
-srs_error_t SrsFormat::video_avc_demux(SrsBuffer *stream, int64_t timestamp)
-{
- srs_error_t err = srs_success;
-
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "video avc demux shall atleast 1bytes");
- }
-
- // Parse the frame type and the first bit indicates the ext header.
- uint8_t frame_type = stream->read_1bytes();
- bool is_ext_header = frame_type & 0x80;
-
- // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
- SrsVideoCodecId codec_id = SrsVideoCodecIdForbidden;
- SrsVideoAvcFrameTrait packet_type = SrsVideoAvcFrameTraitForbidden;
- if (!is_ext_header) {
- // See rtmp_specification_1.0.pdf
- codec_id = (SrsVideoCodecId)(frame_type & 0x0f);
- frame_type = (frame_type >> 4) & 0x0f;
- } else {
- // See https://github.com/veovera/enhanced-rtmp
- packet_type = (SrsVideoAvcFrameTrait)(frame_type & 0x0f);
- frame_type = (frame_type >> 4) & 0x07;
-
- if (!stream->require(4)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "fourCC requires 4bytes, only %dbytes", stream->left());
- }
-
- uint32_t four_cc = stream->read_4bytes();
- if (four_cc == 0x68766331) { // 'hvc1'=0x68766331
- codec_id = SrsVideoCodecIdHEVC;
- }
- }
-
- if (!vcodec) {
- vcodec = new SrsVideoCodecConfig();
- }
-
- if (!video) {
- video = new SrsVideoFrame();
- }
-
- if ((err = video->initialize(vcodec)) != srs_success) {
- return srs_error_wrap(err, "init video");
- }
-
- video->frame_type = (SrsVideoAvcFrameType)frame_type;
-
- // ignore info frame without error,
- // @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
- if (video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) {
- srs_warn("avc ignore the info frame");
- return err;
- }
-
- // Check codec for H.264 and H.265.
- bool codec_ok = (codec_id == SrsVideoCodecIdAVC);
- codec_ok = codec_ok ? true : (codec_id == SrsVideoCodecIdHEVC);
- if (!codec_ok) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "only support video H.264/H.265, actual=%d", codec_id);
- }
- vcodec->id = codec_id;
-
- int32_t composition_time = 0;
- if (!is_ext_header) {
- // See rtmp_specification_1.0.pdf
- if (!stream->require(4)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires 4bytes, only %dbytes", stream->left());
- }
- packet_type = (SrsVideoAvcFrameTrait)stream->read_1bytes();
- composition_time = stream->read_3bytes();
- } else {
- // See https://github.com/veovera/enhanced-rtmp
- if (packet_type == SrsVideoHEVCFrameTraitPacketTypeCodedFrames) {
- if (!stream->require(3)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires 3 bytes, only %dbytes", stream->left());
- }
- composition_time = stream->read_3bytes();
- }
- }
-
- // pts = dts + cts.
- video->dts = timestamp;
- video->cts = composition_time;
- video->avc_packet_type = packet_type;
-
- // Update the RAW AVC data.
- raw = stream->data() + stream->pos();
- nb_raw = stream->size() - stream->pos();
-
- // Parse sequence header for H.265/HEVC.
- if (codec_id == SrsVideoCodecIdHEVC) {
- if (packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
- // TODO: demux vps/sps/pps for hevc
- if ((err = hevc_demux_hvcc(stream)) != srs_success) {
- return srs_error_wrap(err, "demux hevc VPS/SPS/PPS");
- }
- } else if (packet_type == SrsVideoAvcFrameTraitNALU || packet_type == SrsVideoHEVCFrameTraitPacketTypeCodedFramesX) {
- // TODO: demux nalu for hevc
- if ((err = video_nalu_demux(stream)) != srs_success) {
- return srs_error_wrap(err, "demux hevc NALU");
- }
- }
- return err;
- }
-
- // Parse sequence header for H.264/AVC.
- if (packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
- // TODO: FIXME: Maybe we should ignore any error for parsing sps/pps.
- if ((err = avc_demux_sps_pps(stream)) != srs_success) {
- return srs_error_wrap(err, "demux SPS/PPS");
- }
- } else if (packet_type == SrsVideoAvcFrameTraitNALU) {
- if ((err = video_nalu_demux(stream)) != srs_success) {
- return srs_error_wrap(err, "demux NALU");
- }
- } else {
- // ignored.
- }
-
- return err;
-}
-
-// For media server, we don't care the codec, so we just try to parse sps-pps, and we could ignore any error if fail.
-// LCOV_EXCL_START
-
-// struct ptl
-SrsHevcProfileTierLevel::SrsHevcProfileTierLevel()
-{
- general_profile_space = 0;
- general_tier_flag = 0;
- general_profile_idc = 0;
- memset(general_profile_compatibility_flag, 0, 32);
- general_progressive_source_flag = 0;
- general_interlaced_source_flag = 0;
- general_non_packed_constraint_flag = 0;
- general_frame_only_constraint_flag = 0;
- general_max_12bit_constraint_flag = 0;
- general_max_10bit_constraint_flag = 0;
- general_max_8bit_constraint_flag = 0;
- general_max_422chroma_constraint_flag = 0;
- general_max_420chroma_constraint_flag = 0;
- general_max_monochrome_constraint_flag = 0;
- general_intra_constraint_flag = 0;
- general_one_picture_only_constraint_flag = 0;
- general_lower_bit_rate_constraint_flag = 0;
- general_max_14bit_constraint_flag = 0;
- general_reserved_zero_7bits = 0;
- general_reserved_zero_33bits = 0;
- general_reserved_zero_34bits = 0;
- general_reserved_zero_35bits = 0;
- general_reserved_zero_43bits = 0;
- general_inbld_flag = 0;
- general_reserved_zero_bit = 0;
- general_level_idc = 0;
- memset(reserved_zero_2bits, 0, 8);
-}
-
-SrsHevcProfileTierLevel::~SrsHevcProfileTierLevel()
-{
-}
-
-// Parse the hevc vps/sps/pps
-srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer *stream)
-{
- srs_error_t err = srs_success;
-
- int avc_extra_size = stream->size() - stream->pos();
- if (avc_extra_size > 0) {
- char *copy_stream_from = stream->data() + stream->pos();
- vcodec->avc_extra_data = std::vector(copy_stream_from, copy_stream_from + avc_extra_size);
- }
-
- const int HEVC_MIN_SIZE = 23; // From configuration_version to numOfArrays
- if (!stream->require(HEVC_MIN_SIZE)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires %d only %d bytes", HEVC_MIN_SIZE, stream->left());
- }
-
- SrsHevcDecoderConfigurationRecord *dec_conf_rec_p = &(vcodec->hevc_dec_conf_record_);
- dec_conf_rec_p->configuration_version = stream->read_1bytes();
- if (dec_conf_rec_p->configuration_version != 1) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "invalid version=%d", dec_conf_rec_p->configuration_version);
- }
-
- // Read general_profile_space(2bits), general_tier_flag(1bit), general_profile_idc(5bits)
- uint8_t data_byte = stream->read_1bytes();
- dec_conf_rec_p->general_profile_space = (data_byte >> 6) & 0x03;
- dec_conf_rec_p->general_tier_flag = (data_byte >> 5) & 0x01;
- dec_conf_rec_p->general_profile_idc = data_byte & 0x1F;
- srs_info("hevc version:%d, general_profile_space:%d, general_tier_flag:%d, general_profile_idc:%d",
- dec_conf_rec_p->configuration_version, dec_conf_rec_p->general_profile_space, dec_conf_rec_p->general_tier_flag,
- dec_conf_rec_p->general_profile_idc);
-
- // general_profile_compatibility_flags: 32bits
- dec_conf_rec_p->general_profile_compatibility_flags = (uint32_t)stream->read_4bytes();
-
- // general_constraint_indicator_flags: 48bits
- uint64_t data_64bit = (uint64_t)stream->read_4bytes();
- data_64bit = (data_64bit << 16) | (stream->read_2bytes());
- dec_conf_rec_p->general_constraint_indicator_flags = data_64bit;
-
- // general_level_idc: 8bits
- dec_conf_rec_p->general_level_idc = stream->read_1bytes();
- // min_spatial_segmentation_idc: xxxx 14bits
- dec_conf_rec_p->min_spatial_segmentation_idc = stream->read_2bytes() & 0x0fff;
- // parallelism_type: xxxx xx 2bits
- dec_conf_rec_p->parallelism_type = stream->read_1bytes() & 0x03;
- // chroma_format: xxxx xx 2bits
- dec_conf_rec_p->chroma_format = stream->read_1bytes() & 0x03;
- // bit_depth_luma_minus8: xxxx x 3bits
- dec_conf_rec_p->bit_depth_luma_minus8 = stream->read_1bytes() & 0x07;
- // bit_depth_chroma_minus8: xxxx x 3bits
- dec_conf_rec_p->bit_depth_chroma_minus8 = stream->read_1bytes() & 0x07;
- srs_info("general_constraint_indicator_flags:0x%x, general_level_idc:%d, min_spatial_segmentation_idc:%d, parallelism_type:%d, chroma_format:%d, bit_depth_luma_minus8:%d, bit_depth_chroma_minus8:%d",
- dec_conf_rec_p->general_constraint_indicator_flags, dec_conf_rec_p->general_level_idc,
- dec_conf_rec_p->min_spatial_segmentation_idc, dec_conf_rec_p->parallelism_type, dec_conf_rec_p->chroma_format,
- dec_conf_rec_p->bit_depth_luma_minus8, dec_conf_rec_p->bit_depth_chroma_minus8);
-
- // avg_frame_rate: 16bits
- vcodec->frame_rate = dec_conf_rec_p->avg_frame_rate = stream->read_2bytes();
- // 8bits: constant_frame_rate(2bits), num_temporal_layers(3bits),
- // temporal_id_nested(1bit), length_size_minus_one(2bits)
- data_byte = stream->read_1bytes();
- dec_conf_rec_p->constant_frame_rate = (data_byte >> 6) & 0x03;
- dec_conf_rec_p->num_temporal_layers = (data_byte >> 3) & 0x07;
- dec_conf_rec_p->temporal_id_nested = (data_byte >> 2) & 0x01;
-
- // Parse the NALU size.
- dec_conf_rec_p->length_size_minus_one = data_byte & 0x03;
- vcodec->NAL_unit_length = dec_conf_rec_p->length_size_minus_one;
-
- // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
- // 5.2.4.1 AVC decoder configuration record
- // 5.2.4.1.2 Semantics
- // The value of this field shall be one of 0, 1, or 3 corresponding to a
- // length encoded with 1, 2, or 4 bytes, respectively.
- if (vcodec->NAL_unit_length == 2) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2");
- }
-
- uint8_t numOfArrays = stream->read_1bytes();
- srs_info("avg_frame_rate:%d, constant_frame_rate:%d, num_temporal_layers:%d, temporal_id_nested:%d, length_size_minus_one:%d, numOfArrays:%d",
- dec_conf_rec_p->avg_frame_rate, dec_conf_rec_p->constant_frame_rate, dec_conf_rec_p->num_temporal_layers,
- dec_conf_rec_p->temporal_id_nested, dec_conf_rec_p->length_size_minus_one, numOfArrays);
-
- // parse vps/pps/sps
- dec_conf_rec_p->nalu_vec.clear();
- for (int index = 0; index < numOfArrays; index++) {
- if (!stream->require(3)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires 3 only %d bytes", stream->left());
- }
- data_byte = stream->read_1bytes();
-
- SrsHevcHvccNalu hevc_unit;
- hevc_unit.array_completeness = (data_byte >> 7) & 0x01;
- hevc_unit.nal_unit_type = data_byte & 0x3f;
- hevc_unit.num_nalus = stream->read_2bytes();
-
- for (int i = 0; i < hevc_unit.num_nalus; i++) {
- if (!stream->require(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "num_nalus requires 2 only %d bytes", stream->left());
- }
-
- SrsHevcNalData data_item;
- data_item.nal_unit_length = stream->read_2bytes();
-
- if (!stream->require(data_item.nal_unit_length)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires %d only %d bytes",
- data_item.nal_unit_length, stream->left());
- }
- // copy vps/pps/sps data
- data_item.nal_unit_data.resize(data_item.nal_unit_length);
-
- stream->read_bytes((char *)(&data_item.nal_unit_data[0]), data_item.nal_unit_length);
- srs_info("hevc nalu type:%d, array_completeness:%d, num_nalus:%d, i:%d, nal_unit_length:%d",
- hevc_unit.nal_unit_type, hevc_unit.array_completeness, hevc_unit.num_nalus, i, data_item.nal_unit_length);
- hevc_unit.nal_data_vec.push_back(data_item);
- }
- dec_conf_rec_p->nalu_vec.push_back(hevc_unit);
-
- // demux nalu
- if ((err = hevc_demux_vps_sps_pps(&hevc_unit)) != srs_success) {
- return srs_error_wrap(err, "hevc demux vps/sps/pps failed");
- }
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::hevc_demux_vps_sps_pps(SrsHevcHvccNalu *nal)
-{
- srs_error_t err = srs_success;
-
- if (nal->nal_data_vec.empty()) {
- return err;
- }
-
- // TODO: FIXME: Support for multiple VPS/SPS/PPS, then pick the first non-empty one.
- char *frame = (char *)(&nal->nal_data_vec[0].nal_unit_data[0]);
- int nb_frame = nal->nal_data_vec[0].nal_unit_length;
- SrsBuffer stream(frame, nb_frame);
-
- // nal data
- switch (nal->nal_unit_type) {
- case SrsHevcNaluType_VPS:
- err = hevc_demux_vps(&stream);
- break;
- case SrsHevcNaluType_SPS:
- err = hevc_demux_sps(&stream);
- break;
- case SrsHevcNaluType_PPS:
- err = hevc_demux_pps(&stream);
- break;
- default:
- break;
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::hevc_demux_vps(SrsBuffer *stream)
-{
- // for NALU, ITU-T H.265 7.3.2.1 Video parameter set RBSP syntax
- // @see 7.3.1.2 NAL unit header syntax
- // @doc ITU-T-H.265-2021.pdf, page 53.
-
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc vps requires 1 only %d bytes", stream->left());
- }
- int8_t nutv = stream->read_1bytes();
-
- // forbidden_zero_bit shall be equal to 0.
- int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
- if (forbidden_zero_bit) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit);
- }
-
- // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
- // @see 7.4.2.2 NAL unit header semantics
- // @doc ITU-T-H.265-2021.pdf, page 86.
- SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f);
- if (nal_unit_type != SrsHevcNaluType_VPS) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc vps nal_unit_type=%d shall be equal to 33", nal_unit_type);
- }
-
- // nuh_layer_id + nuh_temporal_id_plus1
- stream->skip(1);
-
- // decode the rbsp from vps.
- // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
- std::vector rbsp(stream->size());
-
- int nb_rbsp = srs_rbsp_remove_emulation_bytes(stream, rbsp);
-
- return hevc_demux_vps_rbsp((char *)&rbsp[0], nb_rbsp);
-}
-
-srs_error_t SrsFormat::hevc_demux_vps_rbsp(char *rbsp, int nb_rbsp)
-{
- srs_error_t err = srs_success;
-
- // reparse the rbsp.
- SrsBuffer stream(rbsp, nb_rbsp);
-
- // H265 VPS (video_parameter_set_rbsp()) NAL Unit.
- // Section 7.3.2.1 ("Video parameter set RBSP syntax") of the H.265
- // ITU-T-H.265-2021.pdf, page 54.
- if (!stream.require(4)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "vps requires 4 only %d bytes", stream.left());
- }
-
- SrsBitBuffer bs(&stream);
-
- // vps_video_parameter_set_id u(4)
- int vps_video_parameter_set_id = bs.read_bits(4);
- if (vps_video_parameter_set_id < 0 || vps_video_parameter_set_id > SrsHevcMax_VPS_COUNT) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "vps id out of range: %d", vps_video_parameter_set_id);
- }
-
- // select table
- SrsHevcDecoderConfigurationRecord *dec_conf_rec = &(vcodec->hevc_dec_conf_record_);
- SrsHevcRbspVps *vps = &(dec_conf_rec->vps_table[vps_video_parameter_set_id]);
-
- vps->vps_video_parameter_set_id = vps_video_parameter_set_id;
- // vps_base_layer_internal_flag u(1)
- vps->vps_base_layer_internal_flag = bs.read_bit();
- // vps_base_layer_available_flag u(1)
- vps->vps_base_layer_available_flag = bs.read_bit();
- // vps_max_layers_minus1 u(6)
- vps->vps_max_layers_minus1 = bs.read_bits(6);
- // vps_max_sub_layers_minus1 u(3)
- vps->vps_max_sub_layers_minus1 = bs.read_bits(3);
- // vps_temporal_id_nesting_flag u(1)
- vps->vps_temporal_id_nesting_flag = bs.read_bit();
- // vps_reserved_0xffff_16bits u(16)
- vps->vps_reserved_0xffff_16bits = bs.read_bits(16);
-
- // profile_tier_level(1, vps_max_sub_layers_minus1)
- if ((err = hevc_demux_rbsp_ptl(&bs, &vps->ptl, 1, vps->vps_max_sub_layers_minus1)) != srs_success) {
- return srs_error_wrap(err, "vps rbsp ptl vps_max_sub_layers_minus1=%d", vps->vps_max_sub_layers_minus1);
- }
-
- dec_conf_rec->general_profile_idc = vps->ptl.general_profile_idc;
- dec_conf_rec->general_level_idc = vps->ptl.general_level_idc;
- dec_conf_rec->general_tier_flag = vps->ptl.general_tier_flag;
-
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sublayer flag requires 1 only %d bits", bs.left_bits());
- }
-
- // vps_sub_layer_ordering_info_present_flag u(1)
- vps->vps_sub_layer_ordering_info_present_flag = bs.read_bit();
-
- for (int i = (vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_sub_layers_minus1);
- i <= vps->vps_max_sub_layers_minus1; i++) {
- // vps_max_dec_pic_buffering_minus1[i] ue(v)
- if ((err = bs.read_bits_ue(vps->vps_max_dec_pic_buffering_minus1[i])) != srs_success) {
- return srs_error_wrap(err, "max_dec_pic_buffering_minus1");
- }
- // vps_max_num_reorder_pics[i] ue(v)
- if ((err = bs.read_bits_ue(vps->vps_max_num_reorder_pics[i])) != srs_success) {
- return srs_error_wrap(err, "max_num_reorder_pics");
- }
- // vps_max_latency_increase_plus1[i] ue(v)
- if ((err = bs.read_bits_ue(vps->vps_max_latency_increase_plus1[i])) != srs_success) {
- return srs_error_wrap(err, "max_latency_increase_plus1");
- }
- }
-
- if (!bs.require_bits(6)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "vps maxlayer requires 10 only %d bits", bs.left_bits());
- }
-
- // vps_max_layer_id u(6)
- vps->vps_max_layer_id = bs.read_bits(6);
-
- // vps_num_layer_sets_minus1 ue(v)
- if ((err = bs.read_bits_ue(vps->vps_num_layer_sets_minus1)) != srs_success) {
- return srs_error_wrap(err, "num_layer_sets_minus1");
- }
-
- // TODO: FIXME: Implements it, you might parse remain bits for video_parameter_set_rbsp.
- // @see 7.3.2.1 Video parameter set RBSP
- // @doc ITU-T-H.265-2021.pdf, page 54.
-
- return err;
-}
-
-srs_error_t SrsFormat::hevc_demux_sps(SrsBuffer *stream)
-{
- // for NALU, ITU-T H.265 7.3.2.2 Sequence parameter set RBSP syntax
- // @see 7.3.2.2.1 General sequence parameter set RBSP syntax
- // @doc ITU-T-H.265-2021.pdf, page 55.
-
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc sps requires 1 only %d bytes", stream->left());
- }
- int8_t nutv = stream->read_1bytes();
-
- // forbidden_zero_bit shall be equal to 0.
- int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
- if (forbidden_zero_bit) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit);
- }
-
- // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
- // @see 7.4.2.2 NAL unit header semantics
- // @doc ITU-T-H.265-2021.pdf, page 86.
- SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f);
- if (nal_unit_type != SrsHevcNaluType_SPS) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc sps nal_unit_type=%d shall be equal to 33", nal_unit_type);
- }
-
- // nuh_layer_id + nuh_temporal_id_plus1
- stream->skip(1);
-
- // decode the rbsp from sps.
- // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
- std::vector rbsp(stream->size());
-
- int nb_rbsp = srs_rbsp_remove_emulation_bytes(stream, rbsp);
-
- return hevc_demux_sps_rbsp((char *)&rbsp[0], nb_rbsp);
-}
-
-srs_error_t SrsFormat::hevc_demux_sps_rbsp(char *rbsp, int nb_rbsp)
-{
- srs_error_t err = srs_success;
-
- // we donot parse the detail of sps.
- // @see https://github.com/ossrs/srs/issues/474
- if (!avc_parse_sps) {
- return err;
- }
-
- // reparse the rbsp.
- SrsBuffer stream(rbsp, nb_rbsp);
-
- // H265 SPS Nal Unit (seq_parameter_set_rbsp()) parser.
- // Section 7.3.2.2 ("Sequence parameter set RBSP syntax") of the H.265
- // ITU-T-H.265-2021.pdf, page 55.
- if (!stream.require(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps requires 2 only %d bytes", stream.left());
- }
- uint8_t nutv = stream.read_1bytes();
-
- // sps_video_parameter_set_id u(4)
- int sps_video_parameter_set_id = (nutv >> 4) & 0x0f;
- // sps_max_sub_layers_minus1 u(3)
- int sps_max_sub_layers_minus1 = (nutv >> 1) & 0x07;
- // sps_temporal_id_nesting_flag u(1)
- int sps_temporal_id_nesting_flag = nutv & 0x01;
-
- SrsBitBuffer bs(&stream);
-
- // profile tier level...
- SrsHevcProfileTierLevel profile_tier_level;
- // profile_tier_level(1, sps_max_sub_layers_minus1)
- if ((err = hevc_demux_rbsp_ptl(&bs, &profile_tier_level, 1, sps_max_sub_layers_minus1)) != srs_success) {
- return srs_error_wrap(err, "sps rbsp ptl sps_max_sub_layers_minus1=%d", sps_max_sub_layers_minus1);
- }
-
- vcodec->hevc_profile = (SrsHevcProfile)profile_tier_level.general_profile_idc;
- vcodec->hevc_level = (SrsHevcLevel)profile_tier_level.general_level_idc;
-
- // sps_seq_parameter_set_id ue(v)
- uint32_t sps_seq_parameter_set_id = 0;
- if ((err = bs.read_bits_ue(sps_seq_parameter_set_id)) != srs_success) {
- return srs_error_wrap(err, "sps_seq_parameter_set_id");
- }
- if (sps_seq_parameter_set_id < 0 || sps_seq_parameter_set_id >= SrsHevcMax_SPS_COUNT) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps id out of range: %d", sps_seq_parameter_set_id);
- }
-
- // for sps_table
- SrsHevcDecoderConfigurationRecord *dec_conf_rec = &(vcodec->hevc_dec_conf_record_);
- SrsHevcRbspSps *sps = &(dec_conf_rec->sps_table[sps_seq_parameter_set_id]);
-
- sps->sps_video_parameter_set_id = sps_video_parameter_set_id;
- sps->sps_max_sub_layers_minus1 = sps_max_sub_layers_minus1;
- sps->sps_temporal_id_nesting_flag = sps_temporal_id_nesting_flag;
- sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id;
- sps->ptl = profile_tier_level;
-
- // chroma_format_idc ue(v)
- if ((err = bs.read_bits_ue(sps->chroma_format_idc)) != srs_success) {
- return srs_error_wrap(err, "chroma_format_idc");
- }
-
- if (sps->chroma_format_idc == 3) {
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "separate_colour_plane_flag requires 1 only %d bits", bs.left_bits());
- }
-
- // separate_colour_plane_flag u(1)
- sps->separate_colour_plane_flag = bs.read_bit();
- }
-
- // pic_width_in_luma_samples ue(v)
- if ((err = bs.read_bits_ue(sps->pic_width_in_luma_samples)) != srs_success) {
- return srs_error_wrap(err, "pic_width_in_luma_samples");
- }
-
- // pic_height_in_luma_samples ue(v)
- if ((err = bs.read_bits_ue(sps->pic_height_in_luma_samples)) != srs_success) {
- return srs_error_wrap(err, "pic_height_in_luma_samples");
- }
-
- vcodec->width = sps->pic_width_in_luma_samples;
- vcodec->height = sps->pic_height_in_luma_samples;
-
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "conformance_window_flag requires 1 only %d bits", bs.left_bits());
- }
-
- // conformance_window_flag u(1)
- sps->conformance_window_flag = bs.read_bit();
- if (sps->conformance_window_flag) {
- // conf_win_left_offset ue(v)
- if ((err = bs.read_bits_ue(sps->conf_win_left_offset)) != srs_success) {
- return srs_error_wrap(err, "conf_win_left_offset");
- }
- // conf_win_right_offset ue(v)
- if ((err = bs.read_bits_ue(sps->conf_win_right_offset)) != srs_success) {
- return srs_error_wrap(err, "conf_win_right_offset");
- }
- // conf_win_top_offset ue(v)
- if ((err = bs.read_bits_ue(sps->conf_win_top_offset)) != srs_success) {
- return srs_error_wrap(err, "conf_win_top_offset");
- }
- // conf_win_bottom_offset ue(v)
- if ((err = bs.read_bits_ue(sps->conf_win_bottom_offset)) != srs_success) {
- return srs_error_wrap(err, "conf_win_bottom_offset");
- }
-
- // Table 6-1, 7.4.3.2.1
- // ITU-T-H.265-2021.pdf, page 42.
- // Recalculate width and height
- // Note: 1 is added to the manual, but it is not actually used
- // https://gitlab.com/mbunkus/mkvtoolnix/-/issues/1152
- int sub_width_c = ((1 == sps->chroma_format_idc) || (2 == sps->chroma_format_idc)) && (0 == sps->separate_colour_plane_flag) ? 2 : 1;
- int sub_height_c = (1 == sps->chroma_format_idc) && (0 == sps->separate_colour_plane_flag) ? 2 : 1;
- vcodec->width -= (sub_width_c * sps->conf_win_right_offset + sub_width_c * sps->conf_win_left_offset);
- vcodec->height -= (sub_height_c * sps->conf_win_bottom_offset + sub_height_c * sps->conf_win_top_offset);
- }
-
- // bit_depth_luma_minus8 ue(v)
- if ((err = bs.read_bits_ue(sps->bit_depth_luma_minus8)) != srs_success) {
- return srs_error_wrap(err, "bit_depth_luma_minus8");
- }
- // bit_depth_chroma_minus8 ue(v)
- if ((err = bs.read_bits_ue(sps->bit_depth_chroma_minus8)) != srs_success) {
- return srs_error_wrap(err, "bit_depth_chroma_minus8");
- }
-
- // bit depth
- dec_conf_rec->bit_depth_luma_minus8 = sps->bit_depth_luma_minus8 + 8;
- dec_conf_rec->bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8 + 8;
-
- // log2_max_pic_order_cnt_lsb_minus4 ue(v)
- if ((err = bs.read_bits_ue(sps->log2_max_pic_order_cnt_lsb_minus4)) != srs_success) {
- return srs_error_wrap(err, "log2_max_pic_order_cnt_lsb_minus4");
- }
-
- // TODO: FIXME: Implements it, you might parse remain bits for seq_parameter_set_rbsp.
- // 7.3.2.2 Sequence parameter set RBSP syntax
- // ITU-T-H.265-2021.pdf, page 55 ~ page 57.
-
- // 7.3.2.11 RBSP trailing bits syntax
- // ITU-T-H.265-2021.pdf, page 61.
- // rbsp_trailing_bits()
-
- return err;
-}
-
-srs_error_t SrsFormat::hevc_demux_pps(SrsBuffer *stream)
-{
- // for NALU, ITU-T H.265 7.3.2.3 Picture parameter set RBSP syntax
- // @see 7.3.2.3 Picture parameter set RBSP syntax
- // @doc ITU-T-H.265-2021.pdf, page 57.
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc pps requires 1 only %d bytes", stream->left());
- }
- int8_t nutv = stream->read_1bytes();
-
- // forbidden_zero_bit shall be equal to 0.
- int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
- if (forbidden_zero_bit) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit);
- }
-
- // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
- // @see 7.4.2.2 NAL unit header semantics
- // @doc ITU-T-H.265-2021.pdf, page 86.
- SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f);
- if (nal_unit_type != SrsHevcNaluType_PPS) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc pps nal_unit_type=%d shall be equal to 33", nal_unit_type);
- }
-
- // nuh_layer_id + nuh_temporal_id_plus1
- stream->skip(1);
-
- // decode the rbsp from pps.
- // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
- std::vector rbsp(stream->size());
-
- int nb_rbsp = srs_rbsp_remove_emulation_bytes(stream, rbsp);
-
- return hevc_demux_pps_rbsp((char *)&rbsp[0], nb_rbsp);
-}
-
-srs_error_t SrsFormat::hevc_demux_pps_rbsp(char *rbsp, int nb_rbsp)
-{
- srs_error_t err = srs_success;
-
- // reparse the rbsp.
- SrsBuffer stream(rbsp, nb_rbsp);
-
- // H265 PPS NAL Unit (pic_parameter_set_rbsp()) parser.
- // Section 7.3.2.3 ("Picture parameter set RBSP syntax") of the H.265
- // ITU-T-H.265-2021.pdf, page 57.
- SrsBitBuffer bs(&stream);
-
- // pps_pic_parameter_set_id ue(v)
- uint32_t pps_pic_parameter_set_id = 0;
- if ((err = bs.read_bits_ue(pps_pic_parameter_set_id)) != srs_success) {
- return srs_error_wrap(err, "pps_pic_parameter_set_id");
- }
- if (pps_pic_parameter_set_id < 0 || pps_pic_parameter_set_id >= SrsHevcMax_PPS_COUNT) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps id out of range: %d", pps_pic_parameter_set_id);
- }
-
- // select table
- SrsHevcDecoderConfigurationRecord *dec_conf_rec = &(vcodec->hevc_dec_conf_record_);
- SrsHevcRbspPps *pps = &(dec_conf_rec->pps_table[pps_pic_parameter_set_id]);
- pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id;
-
- // pps_seq_parameter_set_id ue(v)
- uint32_t pps_seq_parameter_set_id = 0;
- if ((err = bs.read_bits_ue(pps_seq_parameter_set_id)) != srs_success) {
- return srs_error_wrap(err, "pps_seq_parameter_set_id");
- }
- pps->pps_seq_parameter_set_id = pps_seq_parameter_set_id;
-
- if (!bs.require_bits(7)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps slice requires 7 only %d bits", bs.left_bits());
- }
-
- // dependent_slice_segments_enabled_flag u(1)
- pps->dependent_slice_segments_enabled_flag = bs.read_bit();
- // output_flag_present_flag u(1)
- pps->output_flag_present_flag = bs.read_bit();
- // num_extra_slice_header_bits u(3)
- pps->num_extra_slice_header_bits = bs.read_bits(3);
- // sign_data_hiding_enabled_flag u(1)
- pps->sign_data_hiding_enabled_flag = bs.read_bit();
- // cabac_init_present_flag u(1)
- pps->cabac_init_present_flag = bs.read_bit();
-
- // num_ref_idx_l0_default_active_minus1 ue(v)
- if ((err = bs.read_bits_ue(pps->num_ref_idx_l0_default_active_minus1)) != srs_success) {
- return srs_error_wrap(err, "num_ref_idx_l0_default_active_minus1");
- }
- // num_ref_idx_l1_default_active_minus1 ue(v)
- if ((err = bs.read_bits_ue(pps->num_ref_idx_l1_default_active_minus1)) != srs_success) {
- return srs_error_wrap(err, "num_ref_idx_l1_default_active_minus1");
- }
- // init_qp_minus26 se(v)
- if ((err = bs.read_bits_se(pps->init_qp_minus26)) != srs_success) {
- return srs_error_wrap(err, "init_qp_minus26");
- }
-
- if (!bs.require_bits(3)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps requires 3 only %d bits", bs.left_bits());
- }
-
- // constrained_intra_pred_flag u(1)
- pps->constrained_intra_pred_flag = bs.read_bit();
- // transform_skip_enabled_flag u(1)
- pps->transform_skip_enabled_flag = bs.read_bit();
- // cu_qp_delta_enabled_flag u(1)
- pps->cu_qp_delta_enabled_flag = bs.read_bit();
- if (pps->cu_qp_delta_enabled_flag) {
- // diff_cu_qp_delta_depth ue(v)
- if ((err = bs.read_bits_ue(pps->diff_cu_qp_delta_depth)) != srs_success) {
- return srs_error_wrap(err, "diff_cu_qp_delta_depth");
- }
- }
- // pps_cb_qp_offset se(v)
- if ((err = bs.read_bits_se(pps->pps_cb_qp_offset)) != srs_success) {
- return srs_error_wrap(err, "pps_cb_qp_offset");
- }
- // pps_cr_qp_offset se(v)
- if ((err = bs.read_bits_se(pps->pps_cr_qp_offset)) != srs_success) {
- return srs_error_wrap(err, "pps_cr_qp_offset");
- }
-
- if (!bs.require_bits(6)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps slice_chroma_qp requires 6 only %d bits", bs.left_bits());
- }
-
- // pps_slice_chroma_qp_offsets_present_flag u(1)
- pps->pps_slice_chroma_qp_offsets_present_flag = bs.read_bit();
- // weighted_pred_flag u(1)
- pps->weighted_pred_flag = bs.read_bit();
- // weighted_bipred_flag u(1)
- pps->weighted_bipred_flag = bs.read_bit();
- // transquant_bypass_enabled_flag u(1)
- pps->transquant_bypass_enabled_flag = bs.read_bit();
- // tiles_enabled_flag u(1)
- pps->tiles_enabled_flag = bs.read_bit();
- // entropy_coding_sync_enabled_flag u(1)
- pps->entropy_coding_sync_enabled_flag = bs.read_bit();
-
- if (pps->tiles_enabled_flag) {
- // num_tile_columns_minus1 ue(v)
- if ((err = bs.read_bits_ue(pps->num_tile_columns_minus1)) != srs_success) {
- return srs_error_wrap(err, "num_tile_columns_minus1");
- }
- // num_tile_rows_minus1 ue(v)
- if ((err = bs.read_bits_ue(pps->num_tile_rows_minus1)) != srs_success) {
- return srs_error_wrap(err, "num_tile_rows_minus1");
- }
-
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "uniform_spacing_flag requires 1 only %d bits", bs.left_bits());
- }
-
- // uniform_spacing_flag u(1)
- pps->uniform_spacing_flag = bs.read_bit();
- if (!pps->uniform_spacing_flag) {
- pps->column_width_minus1.resize(pps->num_tile_columns_minus1);
- pps->row_height_minus1.resize(pps->num_tile_rows_minus1);
-
- for (int i = 0; i < (int)pps->num_tile_columns_minus1; i++) {
- // column_width_minus1[i] ue(v)
- if ((err = bs.read_bits_ue(pps->column_width_minus1[i])) != srs_success) {
- return srs_error_wrap(err, "column_width_minus1");
- }
- }
-
- for (int i = 0; i < (int)pps->num_tile_rows_minus1; i++) {
- // row_height_minus1[i] ue(v)
- if ((err = bs.read_bits_ue(pps->row_height_minus1[i])) != srs_success) {
- return srs_error_wrap(err, "row_height_minus1");
- }
- }
- }
-
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "loop_filter_across_tiles_enabled_flag requires 1 only %d bits", bs.left_bits());
- }
-
- // loop_filter_across_tiles_enabled_flag u(1)
- pps->loop_filter_across_tiles_enabled_flag = bs.read_bit();
- }
-
- if (!bs.require_bits(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps loop deblocking filter requires 2 only %d bits", bs.left_bits());
- }
-
- // pps_loop_filter_across_slices_enabled_flag u(1)
- pps->pps_loop_filter_across_slices_enabled_flag = bs.read_bit();
- // deblocking_filter_control_present_flag u(1)
- pps->deblocking_filter_control_present_flag = bs.read_bit();
- if (pps->deblocking_filter_control_present_flag) {
- if (!bs.require_bits(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps loop deblocking filter flag requires 2 only %d bits", bs.left_bits());
- }
-
- // deblocking_filter_override_enabled_flag u(1)
- pps->deblocking_filter_override_enabled_flag = bs.read_bit();
- // pps_deblocking_filter_disabled_flag u(1)
- pps->pps_deblocking_filter_disabled_flag = bs.read_bit();
- if (!pps->pps_deblocking_filter_disabled_flag) {
- // pps_beta_offset_div2 se(v)
- if ((err = bs.read_bits_se(pps->pps_beta_offset_div2)) != srs_success) {
- return srs_error_wrap(err, "pps_beta_offset_div2");
- }
- // pps_tc_offset_div2 se(v)
- if ((err = bs.read_bits_se(pps->pps_tc_offset_div2)) != srs_success) {
- return srs_error_wrap(err, "pps_tc_offset_div2");
- }
- }
- }
-
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps scaling_list_data requires 1 only %d bits", bs.left_bits());
- }
-
- // pps_scaling_list_data_present_flag u(1)
- pps->pps_scaling_list_data_present_flag = bs.read_bit();
- if (pps->pps_scaling_list_data_present_flag) {
- // 7.3.4 Scaling list data syntax
- SrsHevcScalingListData *sld = &pps->scaling_list_data;
- for (int sizeId = 0; sizeId < 4; sizeId++) {
- for (int matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
- // scaling_list_pred_mode_flag u(1)
- sld->scaling_list_pred_mode_flag[sizeId][matrixId] = bs.read_bit();
- if (!sld->scaling_list_pred_mode_flag[sizeId][matrixId]) {
- // scaling_list_pred_matrix_id_delta ue(v)
- if ((err = bs.read_bits_ue(sld->scaling_list_pred_matrix_id_delta[sizeId][matrixId])) != srs_success) {
- return srs_error_wrap(err, "scaling_list_pred_matrix_id_delta");
- }
- } else {
- int nextCoef = 8;
- int coefNum = srs_min(64, (1 << (4 + (sizeId << 1))));
- sld->coefNum = coefNum; // tmp store
- if (sizeId > 1) {
- // scaling_list_dc_coef_minus8 se(v)
- if ((err = bs.read_bits_se(sld->scaling_list_dc_coef_minus8[sizeId - 2][matrixId])) != srs_success) {
- return srs_error_wrap(err, "scaling_list_dc_coef_minus8");
- }
- nextCoef = sld->scaling_list_dc_coef_minus8[sizeId - 2][matrixId] + 8;
- }
-
- for (int i = 0; i < sld->coefNum; i++) {
- // scaling_list_delta_coef se(v)
- int scaling_list_delta_coef = 0;
- if ((err = bs.read_bits_se(scaling_list_delta_coef)) != srs_success) {
- return srs_error_wrap(err, "scaling_list_delta_coef");
- }
- nextCoef = (nextCoef + scaling_list_delta_coef + 256) % 256;
- sld->ScalingList[sizeId][matrixId][i] = nextCoef;
- }
- }
- }
- }
- }
-
- if (!bs.require_bits(1)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "lists_modification_present_flag requires 1 only %d bits", bs.left_bits());
- }
- // lists_modification_present_flag u(1)
- pps->lists_modification_present_flag = bs.read_bit();
-
- // log2_parallel_merge_level_minus2 ue(v)
- if ((err = bs.read_bits_ue(pps->log2_parallel_merge_level_minus2)) != srs_success) {
- return srs_error_wrap(err, "log2_parallel_merge_level_minus2");
- }
-
- if (!bs.require_bits(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "extension_present_flag requires 2 only %d bits", bs.left_bits());
- }
-
- // slice_segment_header_extension_present_flag u(1)
- pps->slice_segment_header_extension_present_flag = bs.read_bit();
- // pps_extension_present_flag u(1)
- pps->pps_extension_present_flag = bs.read_bit();
- if (pps->pps_extension_present_flag) {
- if (!bs.require_bits(8)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps_range_extension_flag requires 8 only %d bits", bs.left_bits());
- }
-
- // pps_range_extension_flag u(1)
- pps->pps_range_extension_flag = bs.read_bit();
- // pps_multilayer_extension_flag u(1)
- pps->pps_multilayer_extension_flag = bs.read_bit();
- // pps_3d_extension_flag u(1)
- pps->pps_3d_extension_flag = bs.read_bit();
- // pps_scc_extension_flag u(1)
- pps->pps_scc_extension_flag = bs.read_bit();
- // pps_extension_4bits u(4)
- pps->pps_extension_4bits = bs.read_bits(4);
- }
-
- // TODO: FIXME: Implements it, you might parse remain bits for pic_parameter_set_rbsp.
- // @see 7.3.2.3 Picture parameter set RBSP syntax
- // @doc ITU-T-H.265-2021.pdf, page 59.
-
- // TODO: FIXME: rbsp_trailing_bits
-
- return err;
-}
-
-srs_error_t SrsFormat::hevc_demux_rbsp_ptl(SrsBitBuffer *bs, SrsHevcProfileTierLevel *ptl, int profile_present_flag, int max_sub_layers_minus1)
-{
- srs_error_t err = srs_success;
-
- // profile_tier_level() parser.
- // Section 7.3.3 ("Profile, tier and level syntax") of the H.265
- // ITU-T-H.265-2021.pdf, page 62.
- if (profile_present_flag) {
- if (!bs->require_bits(88)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl profile requires 88 only %d bits", bs->left_bits());
- }
-
- // profile_space u(2)
- ptl->general_profile_space = bs->read_bits(2);
- // tier_flag u(1)
- ptl->general_tier_flag = bs->read_bit();
- // profile_idc u(5)
- ptl->general_profile_idc = bs->read_bits(5);
- for (int i = 0; i < 32; i++) {
- // profile_compatibility_flag[j] u(1)
- ptl->general_profile_compatibility_flag[i] = bs->read_bit();
- }
- // progressive_source_flag u(1)
- ptl->general_progressive_source_flag = bs->read_bit();
- // interlaced_source_flag u(1)
- ptl->general_interlaced_source_flag = bs->read_bit();
- // non_packed_constraint_flag u(1)
- ptl->general_non_packed_constraint_flag = bs->read_bit();
- // frame_only_constraint_flag u(1)
- ptl->general_frame_only_constraint_flag = bs->read_bit();
- if (ptl->general_profile_idc == 4 || ptl->general_profile_compatibility_flag[4] ||
- ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] ||
- ptl->general_profile_idc == 6 || ptl->general_profile_compatibility_flag[6] ||
- ptl->general_profile_idc == 7 || ptl->general_profile_compatibility_flag[7] ||
- ptl->general_profile_idc == 8 || ptl->general_profile_compatibility_flag[8] ||
- ptl->general_profile_idc == 9 || ptl->general_profile_compatibility_flag[9] ||
- ptl->general_profile_idc == 10 || ptl->general_profile_compatibility_flag[10] ||
- ptl->general_profile_idc == 11 || ptl->general_profile_compatibility_flag[11]) {
- // The number of bits in this syntax structure is not affected by this condition
- // max_12bit_constraint_flag u(1)
- ptl->general_max_12bit_constraint_flag = bs->read_bit();
- // max_10bit_constraint_flag u(1)
- ptl->general_max_10bit_constraint_flag = bs->read_bit();
- // max_8bit_constraint_flag u(1)
- ptl->general_max_8bit_constraint_flag = bs->read_bit();
- // max_422chroma_constraint_flag u(1)
- ptl->general_max_422chroma_constraint_flag = bs->read_bit();
- // max_420chroma_constraint_flag u(1)
- ptl->general_max_420chroma_constraint_flag = bs->read_bit();
- // max_monochrome_constraint_flag u(1)
- ptl->general_max_monochrome_constraint_flag = bs->read_bit();
- // intra_constraint_flag u(1)
- ptl->general_intra_constraint_flag = bs->read_bit();
- // one_picture_only_constraint_flag u(1)
- ptl->general_one_picture_only_constraint_flag = bs->read_bit();
- // lower_bit_rate_constraint_flag u(1)
- ptl->general_lower_bit_rate_constraint_flag = bs->read_bit();
-
- if (ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] == 1 ||
- ptl->general_profile_idc == 9 || ptl->general_profile_compatibility_flag[9] == 1 ||
- ptl->general_profile_idc == 10 || ptl->general_profile_compatibility_flag[10] == 1 ||
- ptl->general_profile_idc == 11 || ptl->general_profile_compatibility_flag[11] == 1) {
- // max_14bit_constraint_flag u(1)
- ptl->general_max_14bit_constraint_flag = bs->read_bit();
- // reserved_zero_33bits u(33)
- uint32_t bits_tmp_hi = bs->read_bit();
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->general_reserved_zero_33bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- } else {
- // reserved_zero_34bits u(34)
- uint32_t bits_tmp_hi = bs->read_bits(2);
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->general_reserved_zero_34bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- }
- } else if (ptl->general_profile_idc == 2 || ptl->general_profile_compatibility_flag[2]) {
- // general_reserved_zero_7bits u(7)
- ptl->general_reserved_zero_7bits = bs->read_bits(7);
- // general_one_picture_only_constraint_flag u(1)
- ptl->general_one_picture_only_constraint_flag = bs->read_bit();
- // general_reserved_zero_35bits u(35)
- uint32_t bits_tmp_hi = bs->read_bits(3);
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->general_reserved_zero_35bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- } else {
- // reserved_zero_43bits u(43)
- uint32_t bits_tmp_hi = bs->read_bits(11);
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->general_reserved_zero_43bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- }
-
- // The number of bits in this syntax structure is not affected by this condition
- if (ptl->general_profile_idc == 1 || ptl->general_profile_compatibility_flag[1] ||
- ptl->general_profile_idc == 2 || ptl->general_profile_compatibility_flag[2] ||
- ptl->general_profile_idc == 3 || ptl->general_profile_compatibility_flag[3] ||
- ptl->general_profile_idc == 4 || ptl->general_profile_compatibility_flag[4] ||
- ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] ||
- ptl->general_profile_idc == 9 || ptl->general_profile_compatibility_flag[9] ||
- ptl->general_profile_idc == 11 || ptl->general_profile_compatibility_flag[11]) {
- // inbld_flag u(1)
- ptl->general_inbld_flag = bs->read_bit();
- } else {
- // reserved_zero_bit u(1)
- ptl->general_reserved_zero_bit = bs->read_bit();
- }
- }
-
- if (!bs->require_bits(8)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl level requires 8 only %d bits", bs->left_bits());
- }
-
- // general_level_idc u(8)
- ptl->general_level_idc = bs->read_8bits();
-
- ptl->sub_layer_profile_present_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_level_present_flag.resize(max_sub_layers_minus1);
- for (int i = 0; i < max_sub_layers_minus1; i++) {
- if (!bs->require_bits(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl present_flag requires 2 only %d bits", bs->left_bits());
- }
- // sub_layer_profile_present_flag[i] u(1)
- ptl->sub_layer_profile_present_flag[i] = bs->read_bit();
- // sub_layer_level_present_flag[i] u(1)
- ptl->sub_layer_level_present_flag[i] = bs->read_bit();
- }
-
- for (int i = max_sub_layers_minus1; max_sub_layers_minus1 > 0 && i < 8; i++) {
- if (!bs->require_bits(2)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl reserved_zero requires 2 only %d bits", bs->left_bits());
- }
- // reserved_zero_2bits[i] u(2)
- ptl->reserved_zero_2bits[i] = bs->read_bits(2);
- }
-
- ptl->sub_layer_profile_space.resize(max_sub_layers_minus1);
- ptl->sub_layer_tier_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_profile_idc.resize(max_sub_layers_minus1);
- ptl->sub_layer_profile_compatibility_flag.resize(max_sub_layers_minus1);
- for (int i = 0; i < max_sub_layers_minus1; i++) {
- ptl->sub_layer_profile_compatibility_flag[i].resize(32);
- }
- ptl->sub_layer_progressive_source_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_interlaced_source_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_non_packed_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_frame_only_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_max_12bit_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_max_10bit_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_max_8bit_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_max_422chroma_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_max_420chroma_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_max_monochrome_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_intra_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_one_picture_only_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_lower_bit_rate_constraint_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_reserved_zero_34bits.resize(max_sub_layers_minus1);
- ptl->sub_layer_reserved_zero_43bits.resize(max_sub_layers_minus1);
- ptl->sub_layer_inbld_flag.resize(max_sub_layers_minus1);
- ptl->sub_layer_reserved_zero_bit.resize(max_sub_layers_minus1);
- ptl->sub_layer_level_idc.resize(max_sub_layers_minus1);
- for (int i = 0; i < max_sub_layers_minus1; i++) {
- if (ptl->sub_layer_profile_present_flag[i]) {
- if (!bs->require_bits(88)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl sub_layer_profile requires 88 only %d bits", bs->left_bits());
- }
- // profile_space u(2)
- ptl->sub_layer_profile_space[i] = bs->read_bits(2);
- // tier_flag u(1)
- ptl->sub_layer_tier_flag[i] = bs->read_bit();
- // profile_idc u(5)
- ptl->sub_layer_profile_idc[i] = bs->read_bits(5);
- for (int j = 0; j < 32; j++) {
- // profile_compatibility_flag[j] u(1)
- ptl->sub_layer_profile_compatibility_flag[i][j] = bs->read_bit();
- }
- // progressive_source_flag u(1)
- ptl->sub_layer_progressive_source_flag[i] = bs->read_bit();
- // interlaced_source_flag u(1)
- ptl->sub_layer_interlaced_source_flag[i] = bs->read_bit();
- // non_packed_constraint_flag u(1)
- ptl->sub_layer_non_packed_constraint_flag[i] = bs->read_bit();
- // frame_only_constraint_flag u(1)
- ptl->sub_layer_frame_only_constraint_flag[i] = bs->read_bit();
- if (ptl->sub_layer_profile_idc[i] == 4 || ptl->sub_layer_profile_compatibility_flag[i][4] ||
- ptl->sub_layer_profile_idc[i] == 5 || ptl->sub_layer_profile_compatibility_flag[i][5] ||
- ptl->sub_layer_profile_idc[i] == 6 || ptl->sub_layer_profile_compatibility_flag[i][6] ||
- ptl->sub_layer_profile_idc[i] == 7 || ptl->sub_layer_profile_compatibility_flag[i][7] ||
- ptl->sub_layer_profile_idc[i] == 8 || ptl->sub_layer_profile_compatibility_flag[i][8] ||
- ptl->sub_layer_profile_idc[i] == 9 || ptl->sub_layer_profile_compatibility_flag[i][9] ||
- ptl->sub_layer_profile_idc[i] == 10 || ptl->sub_layer_profile_compatibility_flag[i][10] ||
- ptl->sub_layer_profile_idc[i] == 11 || ptl->sub_layer_profile_compatibility_flag[i][11]) {
- // The number of bits in this syntax structure is not affected by this condition.
- // max_12bit_constraint_flag u(1)
- ptl->sub_layer_max_12bit_constraint_flag[i] = bs->read_bit();
- // max_10bit_constraint_flag u(1)
- ptl->sub_layer_max_10bit_constraint_flag[i] = bs->read_bit();
- // max_8bit_constraint_flag u(1)
- ptl->sub_layer_max_8bit_constraint_flag[i] = bs->read_bit();
- // max_422chroma_constraint_flag u(1)
- ptl->sub_layer_max_422chroma_constraint_flag[i] = bs->read_bit();
- // max_420chroma_constraint_flag u(1)
- ptl->sub_layer_max_420chroma_constraint_flag[i] = bs->read_bit();
- // max_monochrome_constraint_flag u(1)
- ptl->sub_layer_max_monochrome_constraint_flag[i] = bs->read_bit();
- // intra_constraint_flag u(1)
- ptl->sub_layer_intra_constraint_flag[i] = bs->read_bit();
- // one_picture_only_constraint_flag u(1)
- ptl->sub_layer_one_picture_only_constraint_flag[i] = bs->read_bit();
- // lower_bit_rate_constraint_flag u(1)
- ptl->sub_layer_lower_bit_rate_constraint_flag[i] = bs->read_bit();
-
- if (ptl->sub_layer_profile_idc[i] == 5 ||
- ptl->sub_layer_profile_compatibility_flag[i][5] == 1 ||
- ptl->sub_layer_profile_idc[i] == 9 ||
- ptl->sub_layer_profile_compatibility_flag[i][9] == 1 ||
- ptl->sub_layer_profile_idc[i] == 10 ||
- ptl->sub_layer_profile_compatibility_flag[i][10] == 1 ||
- ptl->sub_layer_profile_idc[i] == 11 ||
- ptl->sub_layer_profile_compatibility_flag[i][11] == 1) {
- // max_14bit_constraint_flag u(1)
- ptl->general_max_14bit_constraint_flag = bs->read_bit();
- // reserved_zero_33bits u(33)
- uint32_t bits_tmp_hi = bs->read_bit();
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->sub_layer_reserved_zero_33bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- } else {
- // reserved_zero_34bits u(34)
- uint32_t bits_tmp_hi = bs->read_bits(2);
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->sub_layer_reserved_zero_34bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- }
- } else if (ptl->sub_layer_profile_idc[i] == 2 || ptl->sub_layer_profile_compatibility_flag[i][2]) {
- // sub_layer_reserved_zero_7bits u(7)
- ptl->sub_layer_reserved_zero_7bits[i] = bs->read_bits(7);
- // sub_layer_one_picture_only_constraint_flag u(1)
- ptl->sub_layer_one_picture_only_constraint_flag[i] = bs->read_bit();
- // sub_layer_reserved_zero_35bits u(35)
- uint32_t bits_tmp_hi = bs->read_bits(3);
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->sub_layer_reserved_zero_35bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- } else {
- // reserved_zero_43bits u(43)
- uint32_t bits_tmp_hi = bs->read_bits(11);
- uint32_t bits_tmp = bs->read_bits(32);
- ptl->sub_layer_reserved_zero_43bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
- }
-
- // The number of bits in this syntax structure is not affected by this condition
- if (ptl->sub_layer_profile_idc[i] == 1 || ptl->sub_layer_profile_compatibility_flag[i][1] ||
- ptl->sub_layer_profile_idc[i] == 2 || ptl->sub_layer_profile_compatibility_flag[i][2] ||
- ptl->sub_layer_profile_idc[i] == 3 || ptl->sub_layer_profile_compatibility_flag[i][3] ||
- ptl->sub_layer_profile_idc[i] == 4 || ptl->sub_layer_profile_compatibility_flag[i][4] ||
- ptl->sub_layer_profile_idc[i] == 5 || ptl->sub_layer_profile_compatibility_flag[i][5] ||
- ptl->sub_layer_profile_idc[i] == 9 || ptl->sub_layer_profile_compatibility_flag[i][9] ||
- ptl->sub_layer_profile_idc[i] == 11 || ptl->sub_layer_profile_compatibility_flag[i][11]) {
- // inbld_flag u(1)
- ptl->sub_layer_inbld_flag[i] = bs->read_bit();
- } else {
- // reserved_zero_bit u(1)
- ptl->sub_layer_reserved_zero_bit[i] = bs->read_bit();
- }
- }
-
- if (ptl->sub_layer_level_present_flag[i]) {
- if (!bs->require_bits(8)) {
- return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl sub_layer_level requires 8 only %d bits", bs->left_bits());
- }
- // sub_layer_level_idc u(8)
- ptl->sub_layer_level_idc[i] = bs->read_bits(8);
- }
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer *stream)
-{
- // AVCDecoderConfigurationRecord
- // 5.2.4.1.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
- int avc_extra_size = stream->size() - stream->pos();
- if (avc_extra_size > 0) {
- char *copy_stream_from = stream->data() + stream->pos();
- vcodec->avc_extra_data = std::vector(copy_stream_from, copy_stream_from + avc_extra_size);
- }
-
- if (!stream->require(6)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode sequence header");
- }
- // int8_t configuration_version = stream->read_1bytes();
- stream->read_1bytes();
- // int8_t AVCProfileIndication = stream->read_1bytes();
- vcodec->avc_profile = (SrsAvcProfile)stream->read_1bytes();
- // int8_t profile_compatibility = stream->read_1bytes();
- stream->read_1bytes();
- // int8_t AVCLevelIndication = stream->read_1bytes();
- vcodec->avc_level = (SrsAvcLevel)stream->read_1bytes();
-
- // parse the NALU size.
- int8_t lengthSizeMinusOne = stream->read_1bytes();
- lengthSizeMinusOne &= 0x03;
- vcodec->NAL_unit_length = lengthSizeMinusOne;
-
- // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
- // 5.2.4.1 AVC decoder configuration record
- // 5.2.4.1.2 Semantics
- // The value of this field shall be one of 0, 1, or 3 corresponding to a
- // length encoded with 1, 2, or 4 bytes, respectively.
- if (vcodec->NAL_unit_length == 2) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2");
- }
-
- // 1 sps, 7.3.2.1 Sequence parameter set RBSP syntax
- // ISO_IEC_14496-10-AVC-2003.pdf, page 45.
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
- }
- int8_t numOfSequenceParameterSets = stream->read_1bytes();
- numOfSequenceParameterSets &= 0x1f;
- if (numOfSequenceParameterSets < 1) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
- }
- // Support for multiple SPS, then pick the first non-empty one.
- for (int i = 0; i < numOfSequenceParameterSets; ++i) {
- if (!stream->require(2)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size");
- }
- uint16_t sequenceParameterSetLength = stream->read_2bytes();
- if (!stream->require(sequenceParameterSetLength)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data");
- }
- if (sequenceParameterSetLength > 0) {
- vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength);
- stream->read_bytes(&vcodec->sequenceParameterSetNALUnit[0], sequenceParameterSetLength);
- }
- }
-
- // 1 pps
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS");
- }
- int8_t numOfPictureParameterSets = stream->read_1bytes();
- numOfPictureParameterSets &= 0x1f;
- if (numOfPictureParameterSets < 1) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
- }
- // Support for multiple PPS, then pick the first non-empty one.
- for (int i = 0; i < numOfPictureParameterSets; ++i) {
- if (!stream->require(2)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size");
- }
- uint16_t pictureParameterSetLength = stream->read_2bytes();
- if (!stream->require(pictureParameterSetLength)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data");
- }
- if (pictureParameterSetLength > 0) {
- vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength);
- stream->read_bytes(&vcodec->pictureParameterSetNALUnit[0], pictureParameterSetLength);
- }
- }
- return avc_demux_sps();
-}
-
-srs_error_t SrsFormat::avc_demux_sps()
-{
- srs_error_t err = srs_success;
-
- if (vcodec->sequenceParameterSetNALUnit.empty()) {
- return err;
- }
-
- char *sps = &vcodec->sequenceParameterSetNALUnit[0];
- int nbsps = (int)vcodec->sequenceParameterSetNALUnit.size();
-
- SrsBuffer stream(sps, nbsps);
-
- // for NALU, 7.3.1 NAL unit syntax
- // ISO_IEC_14496-10-AVC-2012.pdf, page 61.
- if (!stream.require(1)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
- }
- int8_t nutv = stream.read_1bytes();
-
- // forbidden_zero_bit shall be equal to 0.
- int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
- if (forbidden_zero_bit) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "forbidden_zero_bit shall be equal to 0");
- }
-
- // nal_ref_idc not equal to 0 specifies that the content of the NAL unit contains a sequence parameter set or a picture
- // parameter set or a slice of a reference picture or a slice data partition of a reference picture.
- int8_t nal_ref_idc = (nutv >> 5) & 0x03;
- if (!nal_ref_idc) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_ref_idc shall be not be equal to 0");
- }
-
- // 7.4.1 NAL unit semantics
- // ISO_IEC_14496-10-AVC-2012.pdf, page 61.
- // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
- SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(nutv);
- if (nal_unit_type != 7) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7");
- }
-
- // decode the rbsp from sps.
- // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
- std::vector rbsp(vcodec->sequenceParameterSetNALUnit.size());
-
- int nb_rbsp = srs_rbsp_remove_emulation_bytes(&stream, rbsp);
-
- return avc_demux_sps_rbsp((char *)&rbsp[0], nb_rbsp);
-}
-
-srs_error_t SrsFormat::avc_demux_sps_rbsp(char *rbsp, int nb_rbsp)
-{
- srs_error_t err = srs_success;
-
- // we donot parse the detail of sps.
- // @see https://github.com/ossrs/srs/issues/474
- if (!avc_parse_sps) {
- return err;
- }
-
- // reparse the rbsp.
- SrsBuffer stream(rbsp, nb_rbsp);
-
- // for SPS, 7.3.2.1.1 Sequence parameter set data syntax
- // ISO_IEC_14496-10-AVC-2012.pdf, page 62.
- if (!stream.require(3)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps shall atleast 3bytes");
- }
- uint8_t profile_idc = stream.read_1bytes();
- if (!profile_idc) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the profile_idc invalid");
- }
-
- int8_t flags = stream.read_1bytes();
- if (flags & 0x03) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the flags invalid");
- }
-
- uint8_t level_idc = stream.read_1bytes();
- if (!level_idc) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the level_idc invalid");
- }
-
- SrsBitBuffer bs(&stream);
-
- int32_t seq_parameter_set_id = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, seq_parameter_set_id)) != srs_success) {
- return srs_error_wrap(err, "read seq_parameter_set_id");
- }
- if (seq_parameter_set_id < 0) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the seq_parameter_set_id invalid");
- }
-
- int32_t chroma_format_idc = -1;
- if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || profile_idc == 128) {
- if ((err = srs_avc_nalu_read_uev(&bs, chroma_format_idc)) != srs_success) {
- return srs_error_wrap(err, "read chroma_format_idc");
- }
- if (chroma_format_idc == 3) {
- int8_t separate_colour_plane_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, separate_colour_plane_flag)) != srs_success) {
- return srs_error_wrap(err, "read separate_colour_plane_flag");
- }
- }
-
- int32_t bit_depth_luma_minus8 = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, bit_depth_luma_minus8)) != srs_success) {
- return srs_error_wrap(err, "read bit_depth_luma_minus8");
- ;
- }
-
- int32_t bit_depth_chroma_minus8 = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, bit_depth_chroma_minus8)) != srs_success) {
- return srs_error_wrap(err, "read bit_depth_chroma_minus8");
- ;
- }
-
- int8_t qpprime_y_zero_transform_bypass_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, qpprime_y_zero_transform_bypass_flag)) != srs_success) {
- return srs_error_wrap(err, "read qpprime_y_zero_transform_bypass_flag");
- ;
- }
-
- int8_t seq_scaling_matrix_present_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag)) != srs_success) {
- return srs_error_wrap(err, "read seq_scaling_matrix_present_flag");
- ;
- }
- if (seq_scaling_matrix_present_flag) {
- int nb_scmpfs = ((chroma_format_idc != 3) ? 8 : 12);
- for (int i = 0; i < nb_scmpfs; i++) {
- int8_t seq_scaling_matrix_present_flag_i = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag_i)) != srs_success) {
- return srs_error_wrap(err, "read seq_scaling_matrix_present_flag_i");
- ;
- }
- }
- }
- }
-
- int32_t log2_max_frame_num_minus4 = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, log2_max_frame_num_minus4)) != srs_success) {
- return srs_error_wrap(err, "read log2_max_frame_num_minus4");
- ;
- }
-
- int32_t pic_order_cnt_type = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, pic_order_cnt_type)) != srs_success) {
- return srs_error_wrap(err, "read pic_order_cnt_type");
- ;
- }
-
- if (pic_order_cnt_type == 0) {
- int32_t log2_max_pic_order_cnt_lsb_minus4 = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, log2_max_pic_order_cnt_lsb_minus4)) != srs_success) {
- return srs_error_wrap(err, "read log2_max_pic_order_cnt_lsb_minus4");
- ;
- }
- } else if (pic_order_cnt_type == 1) {
- int8_t delta_pic_order_always_zero_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, delta_pic_order_always_zero_flag)) != srs_success) {
- return srs_error_wrap(err, "read delta_pic_order_always_zero_flag");
- ;
- }
-
- int32_t offset_for_non_ref_pic = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, offset_for_non_ref_pic)) != srs_success) {
- return srs_error_wrap(err, "read offset_for_non_ref_pic");
- ;
- }
-
- int32_t offset_for_top_to_bottom_field = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, offset_for_top_to_bottom_field)) != srs_success) {
- return srs_error_wrap(err, "read offset_for_top_to_bottom_field");
- ;
- }
-
- int32_t num_ref_frames_in_pic_order_cnt_cycle = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, num_ref_frames_in_pic_order_cnt_cycle)) != srs_success) {
- return srs_error_wrap(err, "read num_ref_frames_in_pic_order_cnt_cycle");
- ;
- }
- if (num_ref_frames_in_pic_order_cnt_cycle < 0) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the num_ref_frames_in_pic_order_cnt_cycle");
- }
- for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
- int32_t offset_for_ref_frame_i = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, offset_for_ref_frame_i)) != srs_success) {
- return srs_error_wrap(err, "read offset_for_ref_frame_i");
- ;
- }
- }
- }
-
- int32_t max_num_ref_frames = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, max_num_ref_frames)) != srs_success) {
- return srs_error_wrap(err, "read max_num_ref_frames");
- ;
- }
-
- int8_t gaps_in_frame_num_value_allowed_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, gaps_in_frame_num_value_allowed_flag)) != srs_success) {
- return srs_error_wrap(err, "read gaps_in_frame_num_value_allowed_flag");
- ;
- }
-
- int32_t pic_width_in_mbs_minus1 = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, pic_width_in_mbs_minus1)) != srs_success) {
- return srs_error_wrap(err, "read pic_width_in_mbs_minus1");
- ;
- }
-
- int32_t pic_height_in_map_units_minus1 = -1;
- if ((err = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != srs_success) {
- return srs_error_wrap(err, "read pic_height_in_map_units_minus1");
- ;
- }
-
- int8_t frame_mbs_only_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, frame_mbs_only_flag)) != srs_success) {
- return srs_error_wrap(err, "read frame_mbs_only_flag");
- ;
- }
- if (!frame_mbs_only_flag) {
- /* Skip mb_adaptive_frame_field_flag */
- int8_t mb_adaptive_frame_field_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, mb_adaptive_frame_field_flag)) != srs_success) {
- return srs_error_wrap(err, "read mb_adaptive_frame_field_flag");
- ;
- }
- }
-
- /* Skip direct_8x8_inference_flag */
- int8_t direct_8x8_inference_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, direct_8x8_inference_flag)) != srs_success) {
- return srs_error_wrap(err, "read direct_8x8_inference_flag");
- ;
- }
-
- /* We need the following value to evaluate offsets, if any */
- int8_t frame_cropping_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, frame_cropping_flag)) != srs_success) {
- return srs_error_wrap(err, "read frame_cropping_flag");
- ;
- }
- int32_t frame_crop_left_offset = 0, frame_crop_right_offset = 0,
- frame_crop_top_offset = 0, frame_crop_bottom_offset = 0;
- if (frame_cropping_flag) {
- if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_left_offset)) != srs_success) {
- return srs_error_wrap(err, "read frame_crop_left_offset");
- ;
- }
- if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_right_offset)) != srs_success) {
- return srs_error_wrap(err, "read frame_crop_right_offset");
- ;
- }
- if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_top_offset)) != srs_success) {
- return srs_error_wrap(err, "read frame_crop_top_offset");
- ;
- }
- if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_bottom_offset)) != srs_success) {
- return srs_error_wrap(err, "read frame_crop_bottom_offset");
- ;
- }
- }
-
- /* Skip vui_parameters_present_flag */
- int8_t vui_parameters_present_flag = -1;
- if ((err = srs_avc_nalu_read_bit(&bs, vui_parameters_present_flag)) != srs_success) {
- return srs_error_wrap(err, "read vui_parameters_present_flag");
- ;
- }
-
- vcodec->width = ((pic_width_in_mbs_minus1 + 1) * 16) - frame_crop_left_offset * 2 - frame_crop_right_offset * 2;
- vcodec->height = ((2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);
-
- return err;
-}
-
-// LCOV_EXCL_STOP
-
-srs_error_t SrsFormat::video_nalu_demux(SrsBuffer *stream)
-{
- srs_error_t err = srs_success;
-
- // ensure the sequence header demuxed
- if (!vcodec->is_avc_codec_ok()) {
- srs_warn("avc ignore type=%d for no sequence header", SrsVideoAvcFrameTraitNALU);
- return err;
- }
-
- if (vcodec->id == SrsVideoCodecIdHEVC) {
- // TODO: FIXME: Might need to guess format?
- return do_avc_demux_ibmf_format(stream);
- }
-
- // Parse the SPS/PPS in ANNEXB or IBMF format.
- if (vcodec->payload_format == SrsAvcPayloadFormatIbmf) {
- if ((err = avc_demux_ibmf_format(stream)) != srs_success) {
- return srs_error_wrap(err, "avc demux ibmf");
- }
- } else if (vcodec->payload_format == SrsAvcPayloadFormatAnnexb) {
- if ((err = avc_demux_annexb_format(stream)) != srs_success) {
- return srs_error_wrap(err, "avc demux annexb");
- }
- } else {
- if ((err = try_annexb_first ? avc_demux_annexb_format(stream) : avc_demux_ibmf_format(stream)) == srs_success) {
- vcodec->payload_format = try_annexb_first ? SrsAvcPayloadFormatAnnexb : SrsAvcPayloadFormatIbmf;
- } else {
- srs_freep(err);
- if ((err = try_annexb_first ? avc_demux_ibmf_format(stream) : avc_demux_annexb_format(stream)) == srs_success) {
- vcodec->payload_format = try_annexb_first ? SrsAvcPayloadFormatIbmf : SrsAvcPayloadFormatAnnexb;
- } else {
- return srs_error_wrap(err, "avc demux try_annexb_first=%d", try_annexb_first);
- }
- }
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::avc_demux_annexb_format(SrsBuffer *stream)
-{
- srs_error_t err = srs_success;
-
- int pos = stream->pos();
- err = do_avc_demux_annexb_format(stream);
-
- // Restore the stream if error.
- if (err != srs_success) {
- stream->skip(pos - stream->pos());
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::do_avc_demux_annexb_format(SrsBuffer *stream)
-{
- srs_error_t err = srs_success;
-
- // not annexb, try others
- if (!srs_avc_startswith_annexb(stream, NULL)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "not annexb");
- }
-
- // AnnexB
- // B.1.1 Byte stream NAL unit syntax,
- // ISO_IEC_14496-10-AVC-2003.pdf, page 211.
- while (!stream->empty()) {
- // find start code
- int nb_start_code = 0;
- if (!srs_avc_startswith_annexb(stream, &nb_start_code)) {
- return err;
- }
-
- // skip the start code.
- if (nb_start_code > 0) {
- stream->skip(nb_start_code);
- }
-
- // the NALU start bytes.
- char *p = stream->data() + stream->pos();
-
- // get the last matched NALU
- while (!stream->empty()) {
- if (srs_avc_startswith_annexb(stream, NULL)) {
- break;
- }
-
- stream->skip(1);
- }
-
- char *pp = stream->data() + stream->pos();
-
- // skip the empty.
- if (pp - p <= 0) {
- continue;
- }
-
- // got the NALU.
- if ((err = video->add_sample(p, (int)(pp - p))) != srs_success) {
- return srs_error_wrap(err, "add video frame");
- }
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::avc_demux_ibmf_format(SrsBuffer *stream)
-{
- srs_error_t err = srs_success;
-
- int pos = stream->pos();
- err = do_avc_demux_ibmf_format(stream);
-
- // Restore the stream if error.
- if (err != srs_success) {
- stream->skip(pos - stream->pos());
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::do_avc_demux_ibmf_format(SrsBuffer *stream)
-{
- srs_error_t err = srs_success;
-
- int PictureLength = stream->size() - stream->pos();
-
- // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
- // 5.2.4.1 AVC decoder configuration record
- // 5.2.4.1.2 Semantics
- // The value of this field shall be one of 0, 1, or 3 corresponding to a
- // length encoded with 1, 2, or 4 bytes, respectively.
- srs_assert(vcodec->NAL_unit_length != 2);
-
- // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
- for (int i = 0; i < PictureLength;) {
- // unsigned int((NAL_unit_length+1)*8) NALUnitLength;
- // TODO: FIXME: Should ignore error? See https://github.com/ossrs/srs-gb28181/commit/a13b9b54938a14796abb9011e7a8ee779439a452
- if (!stream->require(vcodec->NAL_unit_length + 1)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "PictureLength:%d, i:%d, NaluLength:%d, left:%d",
- PictureLength, i, vcodec->NAL_unit_length, stream->left());
- }
- int32_t NALUnitLength = 0;
- if (vcodec->NAL_unit_length == 3) {
- NALUnitLength = stream->read_4bytes();
- } else if (vcodec->NAL_unit_length == 1) {
- NALUnitLength = stream->read_2bytes();
- } else {
- NALUnitLength = stream->read_1bytes();
- }
-
- // The stream format mighe be incorrect, see: https://github.com/ossrs/srs/issues/183
- if (NALUnitLength < 0) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "PictureLength:%d, i:%d, NaluLength:%d, left:%d, NALUnitLength:%d",
- PictureLength, i, vcodec->NAL_unit_length, stream->left(), NALUnitLength);
- }
-
- // NALUnit
- if (!stream->require(NALUnitLength)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "PictureLength:%d, i:%d, NaluLength:%d, left:%d, NALUnitLength:%d",
- PictureLength, i, vcodec->NAL_unit_length, stream->left(), NALUnitLength);
- }
- // 7.3.1 NAL unit syntax, ISO_IEC_14496-10-AVC-2003.pdf, page 44.
- if ((err = video->add_sample(stream->data() + stream->pos(), NALUnitLength)) != srs_success) {
- return srs_error_wrap(err, "avc add video frame");
- }
-
- stream->skip(NALUnitLength);
- i += vcodec->NAL_unit_length + 1 + NALUnitLength;
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::audio_aac_demux(SrsBuffer *stream, int64_t timestamp)
-{
- srs_error_t err = srs_success;
-
- audio->cts = 0;
- audio->dts = timestamp;
-
- // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
- int8_t sound_format = stream->read_1bytes();
-
- int8_t sound_type = sound_format & 0x01;
- int8_t sound_size = (sound_format >> 1) & 0x01;
- int8_t sound_rate = (sound_format >> 2) & 0x03;
- sound_format = (sound_format >> 4) & 0x0f;
-
- SrsAudioCodecId codec_id = (SrsAudioCodecId)sound_format;
- acodec->id = codec_id;
-
- acodec->sound_type = (SrsAudioChannels)sound_type;
- acodec->sound_rate = (SrsAudioSampleRate)sound_rate;
- acodec->sound_size = (SrsAudioSampleBits)sound_size;
-
- // we support h.264+mp3 for hls.
- if (codec_id == SrsAudioCodecIdMP3) {
- return srs_error_new(ERROR_HLS_TRY_MP3, "try mp3");
- }
-
- // only support aac
- if (codec_id != SrsAudioCodecIdAAC) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "not supported codec %d", codec_id);
- }
-
- if (!stream->require(1)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode aac_packet_type");
- }
-
- SrsAudioAacFrameTrait aac_packet_type = (SrsAudioAacFrameTrait)stream->read_1bytes();
- audio->aac_packet_type = (SrsAudioAacFrameTrait)aac_packet_type;
-
- // Update the RAW AAC data.
- raw = stream->data() + stream->pos();
- nb_raw = stream->size() - stream->pos();
-
- if (aac_packet_type == SrsAudioAacFrameTraitSequenceHeader) {
- // AudioSpecificConfig
- // 1.6.2.1 AudioSpecificConfig, in ISO_IEC_14496-3-AAC-2001.pdf, page 33.
- int aac_extra_size = stream->size() - stream->pos();
- if (aac_extra_size > 0) {
- char *copy_stream_from = stream->data() + stream->pos();
- acodec->aac_extra_data = std::vector(copy_stream_from, copy_stream_from + aac_extra_size);
-
- if ((err = audio_aac_sequence_header_demux(&acodec->aac_extra_data[0], aac_extra_size)) != srs_success) {
- return srs_error_wrap(err, "demux aac sh");
- }
- }
- } else if (aac_packet_type == SrsAudioAacFrameTraitRawData) {
- // ensure the sequence header demuxed
- if (!acodec->is_aac_codec_ok()) {
- srs_warn("aac ignore type=%d for no sequence header", aac_packet_type);
- return err;
- }
-
- // Raw AAC frame data in UI8 []
- // 6.3 Raw Data, ISO_IEC_13818-7-AAC-2004.pdf, page 28
- if ((err = audio->add_sample(stream->data() + stream->pos(), stream->size() - stream->pos())) != srs_success) {
- return srs_error_wrap(err, "add audio frame");
- }
- } else {
- // ignored.
- }
-
- // reset the sample rate by sequence header
- if (acodec->aac_sample_rate != SrsAacSampleRateUnset) {
- static int srs_aac_srates[] = {
- 96000, 88200, 64000, 48000,
- 44100, 32000, 24000, 22050,
- 16000, 12000, 11025, 8000,
- 7350, 0, 0, 0};
- switch (srs_aac_srates[acodec->aac_sample_rate]) {
- case 11025:
- acodec->sound_rate = SrsAudioSampleRate11025;
- break;
- case 22050:
- acodec->sound_rate = SrsAudioSampleRate22050;
- break;
- case 44100:
- acodec->sound_rate = SrsAudioSampleRate44100;
- break;
- default:
- break;
- };
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::audio_mp3_demux(SrsBuffer *stream, int64_t timestamp, bool fresh)
-{
- srs_error_t err = srs_success;
-
- audio->cts = 0;
- audio->dts = timestamp;
- audio->aac_packet_type = fresh ? SrsAudioMp3FrameTraitSequenceHeader : SrsAudioMp3FrameTraitRawData;
-
- // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
- int8_t sound_format = stream->read_1bytes();
-
- int8_t sound_type = sound_format & 0x01;
- int8_t sound_size = (sound_format >> 1) & 0x01;
- int8_t sound_rate = (sound_format >> 2) & 0x03;
- sound_format = (sound_format >> 4) & 0x0f;
-
- SrsAudioCodecId codec_id = (SrsAudioCodecId)sound_format;
- acodec->id = codec_id;
-
- acodec->sound_type = (SrsAudioChannels)sound_type;
- acodec->sound_rate = (SrsAudioSampleRate)sound_rate;
- acodec->sound_size = (SrsAudioSampleBits)sound_size;
-
- // we always decode aac then mp3.
- srs_assert(acodec->id == SrsAudioCodecIdMP3);
-
- // Update the RAW MP3 data. Note the start is 12 bits syncword 0xFFF, so we should not skip any bytes, for detail
- // please see ISO_IEC_11172-3-MP3-1993.pdf page 20 and 26.
- raw = stream->data() + stream->pos();
- nb_raw = stream->size() - stream->pos();
-
- // mp3 payload.
- if ((err = audio->add_sample(raw, nb_raw)) != srs_success) {
- return srs_error_wrap(err, "add audio frame");
- }
-
- return err;
-}
-
-srs_error_t SrsFormat::audio_aac_sequence_header_demux(char *data, int size)
-{
- srs_error_t err = srs_success;
-
- SrsUniquePtr buffer(new SrsBuffer(data, size));
-
- // only need to decode the first 2bytes:
- // audioObjectType, aac_profile, 5bits.
- // samplingFrequencyIndex, aac_sample_rate, 4bits.
- // channelConfiguration, aac_channels, 4bits
- if (!buffer->require(2)) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "audio codec decode aac sh");
- }
- uint8_t profile_ObjectType = buffer->read_1bytes();
- uint8_t samplingFrequencyIndex = buffer->read_1bytes();
-
- acodec->aac_channels = (samplingFrequencyIndex >> 3) & 0x0f;
- samplingFrequencyIndex = ((profile_ObjectType << 1) & 0x0e) | ((samplingFrequencyIndex >> 7) & 0x01);
- profile_ObjectType = (profile_ObjectType >> 3) & 0x1f;
-
- // set the aac sample rate.
- acodec->aac_sample_rate = samplingFrequencyIndex;
-
- // convert the object type in sequence header to aac profile of ADTS.
- acodec->aac_object = (SrsAacObjectType)profile_ObjectType;
- if (acodec->aac_object == SrsAacObjectTypeReserved) {
- return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode sh object %d", profile_ObjectType);
- }
-
- // TODO: FIXME: to support aac he/he-v2, see: ngx_rtmp_codec_parse_aac_header
- // @see: https://github.com/winlinvip/nginx-rtmp-module/commit/3a5f9eea78fc8d11e8be922aea9ac349b9dcbfc2
- //
- // donot force to LC, @see: https://github.com/ossrs/srs/issues/81
- // the source will print the sequence header info.
- // if (aac_profile > 3) {
- // Mark all extended profiles as LC
- // to make Android as happy as possible.
- // @see: ngx_rtmp_hls_parse_aac_header
- // aac_profile = 1;
- //}
-
- return err;
-}
-
bool srs_avc_startswith_annexb(SrsBuffer *stream, int *pnb_start_code)
{
if (!stream) {
diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp
index 667f4e5d2..68c3d32dd 100644
--- a/trunk/src/kernel/srs_kernel_codec.hpp
+++ b/trunk/src/kernel/srs_kernel_codec.hpp
@@ -12,6 +12,9 @@
#include
#include
+#include
+#include
+
class SrsBuffer;
class SrsBitBuffer;
class SrsFormat;
@@ -264,6 +267,8 @@ enum SrsFrameType {
SrsFrameTypeVideo = 9,
// 18 = script data
SrsFrameTypeScript = 18,
+ // 20 = command data
+ SrsFrameTypeCommand = 20,
};
/**
@@ -1107,30 +1112,6 @@ enum SrsHevcLevel {
};
std::string srs_hevc_level2str(SrsHevcLevel level);
-/**
- * A sample is the unit of frame.
- * It's a NALU for H.264, H.265.
- * It's the whole AAC raw data for AAC.
- * @remark Neither SPS/PPS or ASC is sample unit, it's codec sequence header.
- */
-class SrsSample
-{
-public:
- // The size of unit.
- int size;
- // The ptr of unit, user must free it.
- char *bytes;
-
-public:
- SrsSample();
- SrsSample(char *b, int s);
- ~SrsSample();
-
-public:
- // Copy sample, share the bytes pointer.
- SrsSample *copy();
-};
-
/**
* The codec is the information of encoder,
* corresponding to the sequence header of FLV,
@@ -1248,183 +1229,6 @@ public:
virtual bool is_avc_codec_ok();
};
-// A frame, consists of a codec and a group of samples.
-// TODO: FIXME: Rename to packet to follow names of FFmpeg, which means before decoding or after decoding.
-class SrsFrame
-{
-public:
- // The DTS/PTS in milliseconds, which is TBN=1000.
- int64_t dts;
- // PTS = DTS + CTS.
- int32_t cts;
-
-public:
- // The codec info of frame.
- SrsCodecConfig *codec;
- // The actual parsed number of samples.
- int nb_samples;
- // The sampels cache.
- SrsSample samples[SrsMaxNbSamples];
-
-public:
- SrsFrame();
- virtual ~SrsFrame();
-
-public:
- // Initialize the frame, to parse sampels.
- virtual srs_error_t initialize(SrsCodecConfig *c);
- // Add a sample to frame.
- virtual srs_error_t add_sample(char *bytes, int size);
-};
-
-// A audio frame, besides a frame, contains the audio frame info, such as frame type.
-// TODO: FIXME: Rename to packet to follow names of FFmpeg, which means before decoding or after decoding.
-class SrsAudioFrame : public SrsFrame
-{
-public:
- SrsAudioAacFrameTrait aac_packet_type;
-
-public:
- SrsAudioFrame();
- virtual ~SrsAudioFrame();
-
-public:
- virtual SrsAudioCodecConfig *acodec();
-};
-
-// A video frame, besides a frame, contains the video frame info, such as frame type.
-// TODO: FIXME: Rename to packet to follow names of FFmpeg, which means before decoding or after decoding.
-class SrsVideoFrame : public SrsFrame
-{
-public:
- // video specified
- SrsVideoAvcFrameType frame_type;
- SrsVideoAvcFrameTrait avc_packet_type;
- // whether sample_units contains IDR frame.
- bool has_idr;
- // Whether exists AUD NALU.
- bool has_aud;
- // Whether exists SPS/PPS NALU.
- bool has_sps_pps;
- // The first nalu type.
- SrsAvcNaluType first_nalu_type;
-
-public:
- SrsVideoFrame();
- virtual ~SrsVideoFrame();
-
-public:
- // Initialize the frame, to parse sampels.
- virtual srs_error_t initialize(SrsCodecConfig *c);
- // Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data.
- virtual srs_error_t add_sample(char *bytes, int size);
-
-public:
- virtual SrsVideoCodecConfig *vcodec();
-
-public:
- static srs_error_t parse_avc_nalu_type(const SrsSample *sample, SrsAvcNaluType &avc_nalu_type);
- static srs_error_t parse_avc_bframe(const SrsSample *sample, bool &is_b_frame);
- static srs_error_t parse_hevc_nalu_type(const SrsSample *sample, SrsHevcNaluType &hevc_nalu_type);
- static srs_error_t parse_hevc_bframe(const SrsSample *sample, SrsFormat *format, bool &is_b_frame);
-};
-
-/**
- * A codec format, including one or many stream, each stream identified by a frame.
- * For example, a typical RTMP stream format, consits of a video and audio frame.
- * Maybe some RTMP stream only has a audio stream, for instance, redio application.
- */
-class SrsFormat
-{
-public:
- SrsAudioFrame *audio;
- SrsAudioCodecConfig *acodec;
- SrsVideoFrame *video;
- SrsVideoCodecConfig *vcodec;
-
-public:
- char *raw;
- int nb_raw;
-
-public:
- // for sequence header, whether parse the h.264 sps.
- // TODO: FIXME: Refine it.
- bool avc_parse_sps;
- // Whether try to parse in ANNEXB, then by IBMF.
- bool try_annexb_first;
-
-public:
- SrsFormat();
- virtual ~SrsFormat();
-
-public:
- // Initialize the format.
- virtual srs_error_t initialize();
- // When got a parsed audio packet.
- // @param data The data in FLV format.
- virtual srs_error_t on_audio(int64_t timestamp, char *data, int size);
- // When got a parsed video packet.
- // @param data The data in FLV format.
- virtual srs_error_t on_video(int64_t timestamp, char *data, int size);
- // When got a audio aac sequence header.
- virtual srs_error_t on_aac_sequence_header(char *data, int size);
-
-public:
- virtual bool is_aac_sequence_header();
- virtual bool is_mp3_sequence_header();
- // TODO: is avc|hevc|av1 sequence header
- virtual bool is_avc_sequence_header();
-
-private:
- // Demux the video packet in H.264 codec.
- // The packet is muxed in FLV format, defined in flv specification.
- // Demux the sps/pps from sequence header.
- // Demux the samples from NALUs.
- virtual srs_error_t video_avc_demux(SrsBuffer *stream, int64_t timestamp);
-
-private:
- virtual srs_error_t hevc_demux_hvcc(SrsBuffer *stream);
-
-private:
- virtual srs_error_t hevc_demux_vps_sps_pps(SrsHevcHvccNalu *nal);
- virtual srs_error_t hevc_demux_vps_rbsp(char *rbsp, int nb_rbsp);
- virtual srs_error_t hevc_demux_sps_rbsp(char *rbsp, int nb_rbsp);
- virtual srs_error_t hevc_demux_pps_rbsp(char *rbsp, int nb_rbsp);
- virtual srs_error_t hevc_demux_rbsp_ptl(SrsBitBuffer *bs, SrsHevcProfileTierLevel *ptl, int profile_present_flag, int max_sub_layers_minus1);
-
-public:
- virtual srs_error_t hevc_demux_vps(SrsBuffer *stream);
- virtual srs_error_t hevc_demux_sps(SrsBuffer *stream);
- virtual srs_error_t hevc_demux_pps(SrsBuffer *stream);
-
-private:
- // Parse the H.264 SPS/PPS.
- virtual srs_error_t avc_demux_sps_pps(SrsBuffer *stream);
- virtual srs_error_t avc_demux_sps();
- virtual srs_error_t avc_demux_sps_rbsp(char *rbsp, int nb_rbsp);
-
-private:
- // Parse the H.264 or H.265 NALUs.
- virtual srs_error_t video_nalu_demux(SrsBuffer *stream);
- // Demux the avc NALU in "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
- virtual srs_error_t avc_demux_annexb_format(SrsBuffer *stream);
- virtual srs_error_t do_avc_demux_annexb_format(SrsBuffer *stream);
- // Demux the avc NALU in "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
- virtual srs_error_t avc_demux_ibmf_format(SrsBuffer *stream);
- virtual srs_error_t do_avc_demux_ibmf_format(SrsBuffer *stream);
-
-private:
- // Demux the audio packet in AAC codec.
- // Demux the asc from sequence header.
- // Demux the sampels from RAW data.
- virtual srs_error_t audio_aac_demux(SrsBuffer *stream, int64_t timestamp);
- virtual srs_error_t audio_mp3_demux(SrsBuffer *stream, int64_t timestamp, bool fresh);
-
-public:
- // Directly demux the sequence header, without RTMP packet header.
- virtual srs_error_t audio_aac_sequence_header_demux(char *data, int size);
-};
-
// To read H.264 NALU uev.
extern srs_error_t srs_avc_nalu_read_uev(SrsBitBuffer *stream, int32_t &v);
extern srs_error_t srs_avc_nalu_read_bit(SrsBitBuffer *stream, int8_t &v);
diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp
index 390a211ef..0f948626f 100644
--- a/trunk/src/kernel/srs_kernel_flv.cpp
+++ b/trunk/src/kernel/srs_kernel_flv.cpp
@@ -20,13 +20,48 @@ using namespace std;
#include
#include
#include
+#include
#include
#include
#include
-#include
+int srs_rtmp_prefer_cid(SrsFrameType message_type)
+{
+ if (message_type == SrsFrameTypeVideo) {
+ return RTMP_CID_Video;
+ } else if (message_type == SrsFrameTypeAudio) {
+ return RTMP_CID_Audio;
+ } else if (message_type == SrsFrameTypeCommand || message_type == SrsFrameTypeScript) {
+ return RTMP_CID_OverStream;
+ } else if (message_type == (SrsFrameType)RTMP_MSG_AMF0CommandMessage) {
+ return RTMP_CID_OverStream;
+ } else if (message_type == (SrsFrameType)RTMP_MSG_AMF3DataMessage) {
+ return RTMP_CID_OverStream;
+ } else {
+ return RTMP_CID_OverConnection;
+ }
+}
-SrsPps *_srs_pps_objs_msgs = NULL;
+int srs_rtmp_write_chunk_header(SrsMediaPacket *msg, char *cache, int nb_cache, bool c0)
+{
+ int payload_length = msg->payload_.get() ? msg->payload_->size() : 0;
+ int chunk_id = srs_rtmp_prefer_cid(msg->message_type);
+
+ if (c0) {
+ return srs_chunk_header_c0(chunk_id,
+ (uint32_t)msg->timestamp,
+ payload_length,
+ msg->message_type,
+ msg->stream_id,
+ cache,
+ nb_cache);
+ } else {
+ return srs_chunk_header_c3(chunk_id,
+ (uint32_t)msg->timestamp,
+ cache,
+ nb_cache);
+ }
+}
int srs_chunk_header_c0(int prefer_cid, uint32_t timestamp, int32_t payload_length, int8_t message_type, int32_t stream_id, char *cache, int nb_cache)
{
@@ -159,8 +194,6 @@ SrsMessageHeader::SrsMessageHeader()
stream_id = 0;
timestamp = 0;
- // we always use the connection chunk-id
- prefer_cid = RTMP_CID_OverConnection;
}
SrsMessageHeader::~SrsMessageHeader()
@@ -234,9 +267,6 @@ void SrsMessageHeader::initialize_amf0_script(int size, int stream)
timestamp_delta = (int32_t)0;
timestamp = (int64_t)0;
stream_id = (int32_t)stream;
-
- // amf0 script use connection2 chunk-id
- prefer_cid = RTMP_CID_OverConnection2;
}
void SrsMessageHeader::initialize_audio(int size, uint32_t time, int stream)
@@ -246,9 +276,6 @@ void SrsMessageHeader::initialize_audio(int size, uint32_t time, int stream)
timestamp_delta = (int32_t)time;
timestamp = (int64_t)time;
stream_id = (int32_t)stream;
-
- // audio chunk-id
- prefer_cid = RTMP_CID_Audio;
}
void SrsMessageHeader::initialize_video(int size, uint32_t time, int stream)
@@ -258,9 +285,6 @@ void SrsMessageHeader::initialize_video(int size, uint32_t time, int stream)
timestamp_delta = (int32_t)time;
timestamp = (int64_t)time;
stream_id = (int32_t)stream;
-
- // video chunk-id
- prefer_cid = RTMP_CID_Video;
}
SrsCommonMessage::SrsCommonMessage()
@@ -299,126 +323,12 @@ srs_error_t SrsCommonMessage::create(SrsMessageHeader *pheader, char *body, int
return err;
}
-SrsSharedPtrMessage::SrsSharedPtrMessage() : timestamp(0), stream_id(0), message_type(0), prefer_cid(RTMP_CID_OverConnection)
+void SrsCommonMessage::to_msg(SrsMediaPacket *msg)
{
- payload_ = SrsSharedPtr(NULL);
-
- ++_srs_pps_objs_msgs->sugar;
-}
-
-SrsSharedPtrMessage::~SrsSharedPtrMessage()
-{
- // payload_ automatically cleaned up by SrsSharedPtr
-}
-
-srs_error_t SrsSharedPtrMessage::create(SrsCommonMessage *msg)
-{
- srs_error_t err = srs_success;
-
- // Share the memory block from the common message
- payload_ = msg->payload_;
- this->timestamp = msg->header.timestamp;
- this->stream_id = msg->header.stream_id;
- this->message_type = msg->header.message_type;
- this->prefer_cid = msg->header.prefer_cid;
-
- return err;
-}
-
-srs_error_t SrsSharedPtrMessage::create(SrsMessageHeader *pheader, char *payload, int size)
-{
- srs_error_t err = srs_success;
-
- if (size < 0) {
- return srs_error_new(ERROR_RTMP_MESSAGE_CREATE, "create message size=%d", size);
- }
-
- // Create new memory block and attach the payload
- payload_ = SrsSharedPtr(new SrsMemoryBlock());
- payload_->attach(payload, size);
-
- // Set header information
- if (pheader) {
- this->timestamp = pheader->timestamp;
- this->stream_id = pheader->stream_id;
- this->message_type = pheader->message_type;
- this->prefer_cid = pheader->prefer_cid;
- }
-
- return err;
-}
-
-void SrsSharedPtrMessage::wrap(char *payload, int size)
-{
- // Create new memory block and wrap the payload
- payload_ = SrsSharedPtr(new SrsMemoryBlock());
- payload_->attach(payload, size);
-}
-
-bool SrsSharedPtrMessage::check(int stream_id)
-{
- // Ignore error when message has no payload.
- if (!payload_.get()) {
- return true;
- }
-
- // we assume that the stream_id in a group must be the same.
- if (this->stream_id == stream_id) {
- return true;
- }
- this->stream_id = stream_id;
-
- return false;
-}
-
-bool SrsSharedPtrMessage::is_av()
-{
- return message_type == RTMP_MSG_AudioMessage || message_type == RTMP_MSG_VideoMessage;
-}
-
-bool SrsSharedPtrMessage::is_audio()
-{
- return message_type == RTMP_MSG_AudioMessage;
-}
-
-bool SrsSharedPtrMessage::is_video()
-{
- return message_type == RTMP_MSG_VideoMessage;
-}
-
-int SrsSharedPtrMessage::chunk_header(char *cache, int nb_cache, bool c0)
-{
- int payload_length = payload_.get() ? payload_->size() : 0;
-
- if (c0) {
- return srs_chunk_header_c0(prefer_cid, (uint32_t)timestamp,
- payload_length, message_type, stream_id, cache, nb_cache);
- } else {
- return srs_chunk_header_c3(prefer_cid, (uint32_t)timestamp,
- cache, nb_cache);
- }
-}
-
-SrsSharedPtrMessage *SrsSharedPtrMessage::copy()
-{
- SrsSharedPtrMessage *copy = copy2();
-
- copy->timestamp = timestamp;
- copy->stream_id = stream_id;
- copy->message_type = message_type;
- copy->prefer_cid = prefer_cid;
-
- return copy;
-}
-
-SrsSharedPtrMessage *SrsSharedPtrMessage::copy2()
-{
- SrsSharedPtrMessage *copy = new SrsSharedPtrMessage();
-
- // Share the memory block
- copy->payload_ = payload_;
-
- return copy;
+ msg->payload_ = payload_;
+ msg->timestamp = header.timestamp;
+ msg->stream_id = header.stream_id;
+ msg->message_type = (SrsFrameType)header.message_type;
}
SrsFlvTransmuxer::SrsFlvTransmuxer()
@@ -566,7 +476,7 @@ int SrsFlvTransmuxer::size_tag(int data_size)
return SRS_FLV_TAG_HEADER_SIZE + data_size + SRS_FLV_PREVIOUS_TAG_SIZE;
}
-srs_error_t SrsFlvTransmuxer::write_tags(SrsSharedPtrMessage **msgs, int count)
+srs_error_t SrsFlvTransmuxer::write_tags(SrsMediaPacket **msgs, int count)
{
srs_error_t err = srs_success;
@@ -604,7 +514,7 @@ srs_error_t SrsFlvTransmuxer::write_tags(SrsSharedPtrMessage **msgs, int count)
iovec *iovs = iovss;
int nn_real_iovss = 0;
for (int i = 0; i < count; i++) {
- SrsSharedPtrMessage *msg = msgs[i];
+ SrsMediaPacket *msg = msgs[i];
// Cache FLV packet header.
if (msg->is_audio()) {
diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp
index 9a05bb1fc..9fa1ef126 100644
--- a/trunk/src/kernel/srs_kernel_flv.hpp
+++ b/trunk/src/kernel/srs_kernel_flv.hpp
@@ -14,6 +14,8 @@
#include
#include
+#include
+#include
// For srs-librtmp, @see https://github.com/ossrs/srs/issues/213
#ifndef _WIN32
@@ -24,8 +26,8 @@ class SrsBuffer;
class ISrsWriter;
class ISrsReader;
class SrsFileReader;
-class SrsPacket;
-class SrsSample;
+class SrsRtmpCommand;
+class SrsNaluSample;
#define SRS_FLV_TAG_HEADER_SIZE 11
#define SRS_FLV_PREVIOUS_TAG_SIZE 4
@@ -156,12 +158,6 @@ public:
// @remark, we use 64bits for large time for jitter detect and hls.
int64_t timestamp;
-public:
- // Get the prefered cid(chunk stream id) which sendout over.
- // set at decoding, and canbe used for directly send message,
- // For example, dispatch to all connections.
- int prefer_cid;
-
public:
SrsMessageHeader();
virtual ~SrsMessageHeader();
@@ -222,80 +218,9 @@ public:
// @remark user should never free the body.
// @param pheader, the header to copy to the message. NULL to ignore.
virtual srs_error_t create(SrsMessageHeader *pheader, char *body, int size);
-};
-// The shared ptr message.
-// For audio/video/data message that need less memory copy.
-// and only for output.
-//
-// Create first object by constructor and create(),
-// use copy if need reference count message.
-class SrsSharedPtrMessage
-{
- // 4.1. Message Header
-public:
- // Four-byte field that contains a timestamp of the message.
- // The 4 bytes are packed in the big-endian order.
- // @remark, used as calc timestamp when decode and encode time.
- // @remark, we use 64bits for large time for jitter detect and hls.
- int64_t timestamp;
- // 4bytes.
- // Four-byte field that identifies the stream of the message. These
- // bytes are set in big-endian format.
- int32_t stream_id;
- // Message type for determining audio/video/data
- int8_t message_type;
- // Preferred chunk ID for RTMP chunking
- int prefer_cid;
-
-public:
- // 4.2. Message Payload
- SrsSharedPtr payload_;
-
-public:
- SrsSharedPtrMessage();
- virtual ~SrsSharedPtrMessage();
-
-public:
- // Backward compatibility accessors
- char *payload() { return payload_.get() ? payload_->payload() : NULL; }
- int size() { return payload_.get() ? payload_->size() : 0; }
-
-public:
- // Create shared ptr message,
- // copy header, manage the payload of msg,
- // set the payload to NULL to prevent double free.
- // @remark payload of msg set to NULL if success.
- // @remark User should free the msg.
- virtual srs_error_t create(SrsCommonMessage *msg);
- // Create shared ptr message,
- // from the header and payload.
- // @remark user should never free the payload.
- // @param pheader, the header to copy to the message. NULL to ignore.
- virtual srs_error_t create(SrsMessageHeader *pheader, char *payload, int size);
- // Create shared ptr message from RAW payload.
- // @remark Note that the header is set to zero.
- virtual void wrap(char *payload, int size);
- // check prefer cid and stream id.
- // @return whether stream id already set.
- virtual bool check(int stream_id);
-
-public:
- virtual bool is_av();
- virtual bool is_audio();
- virtual bool is_video();
-
-public:
- // generate the chunk header to cache.
- // @return the size of header.
- virtual int chunk_header(char *cache, int nb_cache, bool c0);
-
-public:
- // copy current shared ptr message, use ref-count.
- // @remark, assert object is created.
- virtual SrsSharedPtrMessage *copy();
- // Only copy the buffer, without header fields.
- virtual SrsSharedPtrMessage *copy2();
+ // Convert to shared ptr message.
+ void to_msg(SrsMediaPacket *msg);
};
// Transmux RTMP packets to FLV stream.
@@ -363,7 +288,7 @@ private:
public:
// Write the tags in a time.
- virtual srs_error_t write_tags(SrsSharedPtrMessage **msgs, int count);
+ virtual srs_error_t write_tags(SrsMediaPacket **msgs, int count);
private:
virtual void cache_metadata(char type, char *data, int size, char *cache);
@@ -439,6 +364,17 @@ public:
virtual srs_error_t seek2(int64_t offset);
};
+// Get the prefer cid for message type.
+extern int srs_rtmp_prefer_cid(SrsFrameType message_type);
+
+// Generate the RTMP chunk header for shared ptr message.
+// @param msg, the shared ptr message to generate header for.
+// @param cache, the cache to write header.
+// @param nb_cache, the size of cache.
+// @param c0, whether to use c0 format (true) or c3 format (false).
+// @return the size of header. 0 if cache not enough.
+extern int srs_rtmp_write_chunk_header(SrsMediaPacket *msg, char *cache, int nb_cache, bool c0);
+
// Generate the c0 chunk header for msg.
// @param cache, the cache to write header.
// @param nb_cache, the size of cache.
diff --git a/trunk/src/kernel/srs_kernel_kbps.cpp b/trunk/src/kernel/srs_kernel_kbps.cpp
index 85bc91b5c..cc2f60fc1 100644
--- a/trunk/src/kernel/srs_kernel_kbps.cpp
+++ b/trunk/src/kernel/srs_kernel_kbps.cpp
@@ -154,6 +154,8 @@ SrsPps *_srs_pps_rrtcps = NULL;
// NACK and loss statistics (only _srs_pps_aloss2 was originally in srs_app_server.cpp)
SrsPps *_srs_pps_aloss2 = NULL;
+SrsPps *_srs_pps_objs_msgs = NULL;
+
#if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS)
// Debug thread statistics
SrsPps *_srs_pps_thread_run = NULL;
diff --git a/trunk/src/kernel/srs_kernel_kbps.hpp b/trunk/src/kernel/srs_kernel_kbps.hpp
index f7e2bef08..e77d00d15 100644
--- a/trunk/src/kernel/srs_kernel_kbps.hpp
+++ b/trunk/src/kernel/srs_kernel_kbps.hpp
@@ -167,6 +167,8 @@ extern SrsPps *_srs_pps_objs_rbuf;
extern SrsPps *_srs_pps_objs_msgs;
extern SrsPps *_srs_pps_objs_rothers;
+extern SrsPps *_srs_pps_objs_msgs;
+
#if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS)
// Debug thread statistics
extern SrsPps *_srs_pps_thread_run;
diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp
index 9841c80d5..62e32e0a4 100644
--- a/trunk/src/kernel/srs_kernel_mp4.cpp
+++ b/trunk/src/kernel/srs_kernel_mp4.cpp
@@ -12,6 +12,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/trunk/src/kernel/srs_kernel_packet.cpp b/trunk/src/kernel/srs_kernel_packet.cpp
new file mode 100644
index 000000000..219cd3177
--- /dev/null
+++ b/trunk/src/kernel/srs_kernel_packet.cpp
@@ -0,0 +1,2451 @@
+//
+// Copyright (c) 2013-2025 The SRS Authors
+//
+// SPDX-License-Identifier: MIT
+//
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+SrsNaluSample::SrsNaluSample()
+{
+ size = 0;
+ bytes = NULL;
+}
+
+SrsNaluSample::SrsNaluSample(char *b, int s)
+{
+ size = s;
+ bytes = b;
+}
+
+SrsNaluSample::~SrsNaluSample()
+{
+}
+
+SrsNaluSample *SrsNaluSample::copy()
+{
+ SrsNaluSample *p = new SrsNaluSample();
+ p->bytes = bytes;
+ p->size = size;
+ return p;
+}
+
+SrsMediaPacket::SrsMediaPacket()
+{
+ timestamp = 0;
+ stream_id = 0;
+ message_type = SrsFrameTypeForbidden;
+ payload_ = SrsSharedPtr(NULL);
+
+ ++_srs_pps_objs_msgs->sugar;
+}
+
+SrsMediaPacket::~SrsMediaPacket()
+{
+ // payload_ automatically cleaned up by SrsSharedPtr
+}
+
+void SrsMediaPacket::wrap(char *payload, int size)
+{
+ // Create new memory block and wrap the payload
+ payload_ = SrsSharedPtr(new SrsMemoryBlock());
+ payload_->attach(payload, size);
+}
+
+bool SrsMediaPacket::check(int stream_id)
+{
+ // Ignore error when message has no payload.
+ if (!payload_.get()) {
+ return true;
+ }
+
+ // we assume that the stream_id in a group must be the same.
+ if (this->stream_id == stream_id) {
+ return true;
+ }
+ this->stream_id = stream_id;
+
+ return false;
+}
+
+bool SrsMediaPacket::is_av()
+{
+ return message_type == SrsFrameTypeAudio || message_type == SrsFrameTypeVideo;
+}
+
+bool SrsMediaPacket::is_audio()
+{
+ return message_type == SrsFrameTypeAudio;
+}
+
+bool SrsMediaPacket::is_video()
+{
+ return message_type == SrsFrameTypeVideo;
+}
+
+SrsMediaPacket *SrsMediaPacket::copy()
+{
+ SrsMediaPacket *copy = new SrsMediaPacket();
+
+ copy->timestamp = timestamp;
+ copy->stream_id = stream_id;
+ copy->message_type = message_type;
+ copy->payload_ = payload_;
+
+ return copy;
+}
+
+SrsParsedPacket::SrsParsedPacket()
+{
+ codec = NULL;
+ nb_samples = 0;
+ dts = 0;
+ cts = 0;
+}
+
+SrsParsedPacket::~SrsParsedPacket()
+{
+}
+
+srs_error_t SrsParsedPacket::initialize(SrsCodecConfig *c)
+{
+ codec = c;
+ nb_samples = 0;
+ dts = 0;
+ cts = 0;
+ return srs_success;
+}
+
+srs_error_t SrsParsedPacket::add_sample(char *bytes, int size)
+{
+ srs_error_t err = srs_success;
+
+ // Ignore empty sample.
+ if (!bytes || size <= 0)
+ return err;
+
+ if (nb_samples >= SrsMaxNbSamples) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "Frame samples overflow");
+ }
+
+ SrsNaluSample *sample = &samples[nb_samples++];
+ sample->bytes = bytes;
+ sample->size = size;
+
+ return err;
+}
+
+SrsParsedAudioPacket::SrsParsedAudioPacket()
+{
+ aac_packet_type = SrsAudioAacFrameTraitForbidden;
+}
+
+SrsParsedAudioPacket::~SrsParsedAudioPacket()
+{
+}
+
+SrsAudioCodecConfig *SrsParsedAudioPacket::acodec()
+{
+ return (SrsAudioCodecConfig *)codec;
+}
+
+SrsParsedVideoPacket::SrsParsedVideoPacket()
+{
+ frame_type = SrsVideoAvcFrameTypeForbidden;
+ avc_packet_type = SrsVideoAvcFrameTraitForbidden;
+ has_idr = has_aud = has_sps_pps = false;
+ first_nalu_type = SrsAvcNaluTypeForbidden;
+}
+
+SrsParsedVideoPacket::~SrsParsedVideoPacket()
+{
+}
+
+srs_error_t SrsParsedVideoPacket::initialize(SrsCodecConfig *c)
+{
+ first_nalu_type = SrsAvcNaluTypeForbidden;
+ has_idr = has_sps_pps = has_aud = false;
+ return SrsParsedPacket::initialize(c);
+}
+
+srs_error_t SrsParsedVideoPacket::add_sample(char *bytes, int size)
+{
+ srs_error_t err = srs_success;
+
+ if ((err = SrsParsedPacket::add_sample(bytes, size)) != srs_success) {
+ return srs_error_wrap(err, "add frame");
+ }
+
+ SrsVideoCodecConfig *c = vcodec();
+ if (!bytes || size <= 0)
+ return err;
+
+ // For HEVC(H.265), try to parse the IDR from NALUs.
+ if (c && c->id == SrsVideoCodecIdHEVC) {
+ SrsHevcNaluType nalu_type = SrsHevcNaluTypeParse(bytes[0]);
+ has_idr = SrsIsIRAP(nalu_type);
+ return err;
+ }
+
+ // By default, use AVC(H.264) to parse NALU.
+ // For video, parse the nalu type, set the IDR flag.
+ SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(bytes[0]);
+
+ if (nal_unit_type == SrsAvcNaluTypeIDR) {
+ has_idr = true;
+ } else if (nal_unit_type == SrsAvcNaluTypeSPS || nal_unit_type == SrsAvcNaluTypePPS) {
+ has_sps_pps = true;
+ } else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) {
+ has_aud = true;
+ }
+
+ if (first_nalu_type == SrsAvcNaluTypeReserved) {
+ first_nalu_type = nal_unit_type;
+ }
+
+ return err;
+}
+
+SrsVideoCodecConfig *SrsParsedVideoPacket::vcodec()
+{
+ return (SrsVideoCodecConfig *)codec;
+}
+
+srs_error_t SrsParsedVideoPacket::parse_avc_nalu_type(const SrsNaluSample *sample, SrsAvcNaluType &avc_nalu_type)
+{
+ srs_error_t err = srs_success;
+
+ if (sample == NULL || sample->size < 1) {
+ return srs_error_new(ERROR_NALU_EMPTY, "empty nalu");
+ }
+
+ uint8_t header = sample->bytes[0];
+ avc_nalu_type = SrsAvcNaluTypeParse(header);
+
+ return err;
+}
+
+srs_error_t SrsParsedVideoPacket::parse_avc_bframe(const SrsNaluSample *sample, bool &is_b_frame)
+{
+ srs_error_t err = srs_success;
+
+ SrsAvcNaluType nalu_type;
+ if ((err = parse_avc_nalu_type(sample, nalu_type)) != srs_success) {
+ return srs_error_wrap(err, "parse avc nalu type error");
+ }
+
+ if (nalu_type != SrsAvcNaluTypeNonIDR && nalu_type != SrsAvcNaluTypeDataPartitionA && nalu_type != SrsAvcNaluTypeDataPartitionB && nalu_type != SrsAvcNaluTypeDataPartitionC) {
+ is_b_frame = false;
+ return err;
+ }
+
+ SrsUniquePtr stream(new SrsBuffer(sample->bytes, sample->size));
+
+ // Skip nalu header.
+ stream->skip(1);
+
+ SrsBitBuffer bitstream(stream.get());
+ int32_t first_mb_in_slice = 0;
+ if ((err = srs_avc_nalu_read_uev(&bitstream, first_mb_in_slice)) != srs_success) {
+ return srs_error_wrap(err, "nalu read uev");
+ }
+
+ int32_t slice_type_v = 0;
+ if ((err = srs_avc_nalu_read_uev(&bitstream, slice_type_v)) != srs_success) {
+ return srs_error_wrap(err, "nalu read uev");
+ }
+ SrsAvcSliceType slice_type = (SrsAvcSliceType)slice_type_v;
+
+ is_b_frame = slice_type == SrsAvcSliceTypeB || slice_type == SrsAvcSliceTypeB1;
+ if (is_b_frame) {
+ srs_verbose("nalu_type=%d, slice type=%d", nalu_type, slice_type);
+ }
+
+ return err;
+}
+
+srs_error_t SrsParsedVideoPacket::parse_hevc_nalu_type(const SrsNaluSample *sample, SrsHevcNaluType &hevc_nalu_type)
+{
+ srs_error_t err = srs_success;
+
+ if (sample == NULL || sample->size < 1) {
+ return srs_error_new(ERROR_NALU_EMPTY, "empty hevc nalu");
+ }
+
+ uint8_t header = sample->bytes[0];
+ hevc_nalu_type = SrsHevcNaluTypeParse(header);
+
+ return err;
+}
+
+srs_error_t SrsParsedVideoPacket::parse_hevc_bframe(const SrsNaluSample *sample, SrsFormat *format, bool &is_b_frame)
+{
+ srs_error_t err = srs_success;
+
+ SrsHevcNaluType nalu_type;
+ if ((err = parse_hevc_nalu_type(sample, nalu_type)) != srs_success) {
+ return srs_error_wrap(err, "parse hevc nalu type error");
+ }
+
+ if (nalu_type > SrsHevcNaluType_CODED_SLICE_TFD) {
+ is_b_frame = false;
+ return err;
+ }
+
+ SrsUniquePtr stream(new SrsBuffer(sample->bytes, sample->size));
+ stream->skip(2);
+
+ // @see 7.3.6.1 General slice segment header syntax
+ // @doc ITU-T-H.265-2021.pdf, page 66.
+ SrsBitBuffer bs(stream.get());
+
+ uint8_t first_slice_segment_in_pic_flag = bs.read_bit();
+
+ uint32_t slice_pic_parameter_set_id;
+ if ((err = bs.read_bits_ue(slice_pic_parameter_set_id)) != srs_success) {
+ return srs_error_wrap(err, "read slice pic parameter set id");
+ }
+
+ if (slice_pic_parameter_set_id >= SrsHevcMax_PPS_COUNT) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "slice pic parameter set id out of range: %d", slice_pic_parameter_set_id);
+ }
+
+ SrsHevcRbspPps *pps = &(format->vcodec->hevc_dec_conf_record_.pps_table[slice_pic_parameter_set_id]);
+ if (!pps) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps not found");
+ }
+
+ uint8_t dependent_slice_segment_flag = 0;
+ if (!first_slice_segment_in_pic_flag) {
+ if (pps->dependent_slice_segments_enabled_flag) {
+ dependent_slice_segment_flag = bs.read_bit();
+ }
+ }
+
+ if (dependent_slice_segment_flag) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "dependent slice segment flag is not supported");
+ }
+
+ for (int i = 0; i < pps->num_extra_slice_header_bits; i++) {
+ bs.skip_bits(1);
+ }
+
+ uint32_t slice_type;
+ if ((err = bs.read_bits_ue(slice_type)) != srs_success) {
+ return srs_error_wrap(err, "read slice type");
+ }
+
+ is_b_frame = slice_type == SrsHevcSliceTypeB;
+ if (is_b_frame) {
+ srs_verbose("nalu_type=%d, slice type=%d", nalu_type, slice_type);
+ }
+
+ // no need to evaluate the rest
+
+ return err;
+}
+
+SrsFormat::SrsFormat()
+{
+ acodec = NULL;
+ vcodec = NULL;
+ audio = NULL;
+ video = NULL;
+ avc_parse_sps = true;
+ try_annexb_first = true;
+ raw = NULL;
+ nb_raw = 0;
+}
+
+SrsFormat::~SrsFormat()
+{
+ srs_freep(audio);
+ srs_freep(video);
+ srs_freep(acodec);
+ srs_freep(vcodec);
+}
+
+// CRITICAL: This method is called AFTER the source has been added to the source pool
+// in the fetch_or_create pattern (see PR 4449).
+//
+// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches.
+// This prevents the race condition where multiple coroutines could create duplicate sources
+// for the same stream when context switches occurred during initialization.
+srs_error_t SrsFormat::initialize()
+{
+ if (!vcodec) {
+ vcodec = new SrsVideoCodecConfig();
+ }
+
+ return srs_success;
+}
+
+srs_error_t SrsFormat::on_audio(int64_t timestamp, char *data, int size)
+{
+ srs_error_t err = srs_success;
+
+ if (!data || size <= 0) {
+ srs_info("no audio present, ignore it.");
+ return err;
+ }
+
+ SrsUniquePtr buffer(new SrsBuffer(data, size));
+
+ // We already checked the size is positive and data is not NULL.
+ srs_assert(buffer->require(1));
+
+ // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
+ uint8_t v = buffer->read_1bytes();
+ SrsAudioCodecId codec = (SrsAudioCodecId)((v >> 4) & 0x0f);
+
+ if (codec != SrsAudioCodecIdMP3 && codec != SrsAudioCodecIdAAC && codec != SrsAudioCodecIdOpus) {
+ return err;
+ }
+
+ bool fresh = !acodec;
+ if (!acodec) {
+ acodec = new SrsAudioCodecConfig();
+ }
+ if (!audio) {
+ audio = new SrsParsedAudioPacket();
+ }
+
+ if ((err = audio->initialize(acodec)) != srs_success) {
+ return srs_error_wrap(err, "init audio");
+ }
+
+ // Parse by specified codec.
+ buffer->skip(-1 * buffer->pos());
+
+ if (codec == SrsAudioCodecIdMP3) {
+ return audio_mp3_demux(buffer.get(), timestamp, fresh);
+ } else if (codec == SrsAudioCodecIdAAC) {
+ return audio_aac_demux(buffer.get(), timestamp);
+ } else {
+ return srs_error_new(ERROR_NOT_IMPLEMENTED, "opus demuxer not implemented");
+ }
+}
+
+srs_error_t SrsFormat::on_video(int64_t timestamp, char *data, int size)
+{
+ srs_error_t err = srs_success;
+
+ if (!data || size <= 0) {
+ srs_trace("no video present, ignore it.");
+ return err;
+ }
+
+ SrsUniquePtr buffer(new SrsBuffer(data, size));
+ return video_avc_demux(buffer.get(), timestamp);
+}
+
+srs_error_t SrsFormat::on_aac_sequence_header(char *data, int size)
+{
+ srs_error_t err = srs_success;
+
+ if (!acodec) {
+ acodec = new SrsAudioCodecConfig();
+ }
+ if (!audio) {
+ audio = new SrsParsedAudioPacket();
+ }
+
+ if ((err = audio->initialize(acodec)) != srs_success) {
+ return srs_error_wrap(err, "init audio");
+ }
+
+ return audio_aac_sequence_header_demux(data, size);
+}
+
+bool SrsFormat::is_aac_sequence_header()
+{
+ return acodec && acodec->id == SrsAudioCodecIdAAC && audio && audio->aac_packet_type == SrsAudioAacFrameTraitSequenceHeader;
+}
+
+bool SrsFormat::is_mp3_sequence_header()
+{
+ return acodec && acodec->id == SrsAudioCodecIdMP3 && audio && audio->aac_packet_type == SrsAudioMp3FrameTraitSequenceHeader;
+}
+
+bool SrsFormat::is_avc_sequence_header()
+{
+ bool h264 = (vcodec && vcodec->id == SrsVideoCodecIdAVC);
+ bool h265 = (vcodec && vcodec->id == SrsVideoCodecIdHEVC);
+ bool av1 = (vcodec && vcodec->id == SrsVideoCodecIdAV1);
+ return vcodec && (h264 || h265 || av1) && video && video->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader;
+}
+
+// Remove the emulation bytes from stream, and return num of bytes of the rbsp.
+int srs_rbsp_remove_emulation_bytes(SrsBuffer *stream, std::vector &rbsp)
+{
+ int nb_rbsp = 0;
+ while (!stream->empty()) {
+ rbsp[nb_rbsp] = stream->read_1bytes();
+
+ // .. 00 00 03 xx, the 03 byte should be drop where xx represents any
+ // 2 bit pattern: 00, 01, 10, or 11.
+ if (nb_rbsp >= 2 && rbsp[nb_rbsp - 2] == 0 && rbsp[nb_rbsp - 1] == 0 && rbsp[nb_rbsp] == 3) {
+ // read 1byte more.
+ if (stream->empty()) {
+ nb_rbsp++;
+ break;
+ }
+
+ // |---------------------|----------------------------|
+ // | rbsp | nalu with emulation bytes |
+ // |---------------------|----------------------------|
+ // | 0x00 0x00 0x00 | 0x00 0x00 0x03 0x00 |
+ // | 0x00 0x00 0x01 | 0x00 0x00 0x03 0x01 |
+ // | 0x00 0x00 0x02 | 0x00 0x00 0x03 0x02 |
+ // | 0x00 0x00 0x03 | 0x00 0x00 0x03 0x03 |
+ // | 0x00 0x00 0x03 0x04 | 0x00 0x00 0x03 0x04 |
+ // |---------------------|----------------------------|
+ uint8_t ev = stream->read_1bytes();
+ if (ev > 3) {
+ nb_rbsp++;
+ }
+ rbsp[nb_rbsp] = ev;
+ }
+
+ nb_rbsp++;
+ }
+
+ return nb_rbsp;
+}
+
+srs_error_t SrsFormat::video_avc_demux(SrsBuffer *stream, int64_t timestamp)
+{
+ srs_error_t err = srs_success;
+
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "video avc demux shall atleast 1bytes");
+ }
+
+ // Parse the frame type and the first bit indicates the ext header.
+ uint8_t frame_type = stream->read_1bytes();
+ bool is_ext_header = frame_type & 0x80;
+
+ // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
+ SrsVideoCodecId codec_id = SrsVideoCodecIdForbidden;
+ SrsVideoAvcFrameTrait packet_type = SrsVideoAvcFrameTraitForbidden;
+ if (!is_ext_header) {
+ // See rtmp_specification_1.0.pdf
+ codec_id = (SrsVideoCodecId)(frame_type & 0x0f);
+ frame_type = (frame_type >> 4) & 0x0f;
+ } else {
+ // See https://github.com/veovera/enhanced-rtmp
+ packet_type = (SrsVideoAvcFrameTrait)(frame_type & 0x0f);
+ frame_type = (frame_type >> 4) & 0x07;
+
+ if (!stream->require(4)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "fourCC requires 4bytes, only %dbytes", stream->left());
+ }
+
+ uint32_t four_cc = stream->read_4bytes();
+ if (four_cc == 0x68766331) { // 'hvc1'=0x68766331
+ codec_id = SrsVideoCodecIdHEVC;
+ }
+ }
+
+ if (!vcodec) {
+ vcodec = new SrsVideoCodecConfig();
+ }
+
+ if (!video) {
+ video = new SrsParsedVideoPacket();
+ }
+
+ if ((err = video->initialize(vcodec)) != srs_success) {
+ return srs_error_wrap(err, "init video");
+ }
+
+ video->frame_type = (SrsVideoAvcFrameType)frame_type;
+
+ // ignore info frame without error,
+ // @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
+ if (video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) {
+ srs_warn("avc ignore the info frame");
+ return err;
+ }
+
+ // Check codec for H.264 and H.265.
+ bool codec_ok = (codec_id == SrsVideoCodecIdAVC);
+ codec_ok = codec_ok ? true : (codec_id == SrsVideoCodecIdHEVC);
+ if (!codec_ok) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "only support video H.264/H.265, actual=%d", codec_id);
+ }
+ vcodec->id = codec_id;
+
+ int32_t composition_time = 0;
+ if (!is_ext_header) {
+ // See rtmp_specification_1.0.pdf
+ if (!stream->require(4)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires 4bytes, only %dbytes", stream->left());
+ }
+ packet_type = (SrsVideoAvcFrameTrait)stream->read_1bytes();
+ composition_time = stream->read_3bytes();
+ } else {
+ // See https://github.com/veovera/enhanced-rtmp
+ if (packet_type == SrsVideoHEVCFrameTraitPacketTypeCodedFrames) {
+ if (!stream->require(3)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "requires 3 bytes, only %dbytes", stream->left());
+ }
+ composition_time = stream->read_3bytes();
+ }
+ }
+
+ // pts = dts + cts.
+ video->dts = timestamp;
+ video->cts = composition_time;
+ video->avc_packet_type = packet_type;
+
+ // Update the RAW AVC data.
+ raw = stream->data() + stream->pos();
+ nb_raw = stream->size() - stream->pos();
+
+ // Parse sequence header for H.265/HEVC.
+ if (codec_id == SrsVideoCodecIdHEVC) {
+ if (packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
+ // TODO: demux vps/sps/pps for hevc
+ if ((err = hevc_demux_hvcc(stream)) != srs_success) {
+ return srs_error_wrap(err, "demux hevc VPS/SPS/PPS");
+ }
+ } else if (packet_type == SrsVideoAvcFrameTraitNALU || packet_type == SrsVideoHEVCFrameTraitPacketTypeCodedFramesX) {
+ // TODO: demux nalu for hevc
+ if ((err = video_nalu_demux(stream)) != srs_success) {
+ return srs_error_wrap(err, "demux hevc NALU");
+ }
+ }
+ return err;
+ }
+
+ // Parse sequence header for H.264/AVC.
+ if (packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
+ // TODO: FIXME: Maybe we should ignore any error for parsing sps/pps.
+ if ((err = avc_demux_sps_pps(stream)) != srs_success) {
+ return srs_error_wrap(err, "demux SPS/PPS");
+ }
+ } else if (packet_type == SrsVideoAvcFrameTraitNALU) {
+ if ((err = video_nalu_demux(stream)) != srs_success) {
+ return srs_error_wrap(err, "demux NALU");
+ }
+ } else {
+ // ignored.
+ }
+
+ return err;
+}
+
+// For media server, we don't care the codec, so we just try to parse sps-pps, and we could ignore any error if fail.
+// LCOV_EXCL_START
+
+// struct ptl
+SrsHevcProfileTierLevel::SrsHevcProfileTierLevel()
+{
+ general_profile_space = 0;
+ general_tier_flag = 0;
+ general_profile_idc = 0;
+ memset(general_profile_compatibility_flag, 0, 32);
+ general_progressive_source_flag = 0;
+ general_interlaced_source_flag = 0;
+ general_non_packed_constraint_flag = 0;
+ general_frame_only_constraint_flag = 0;
+ general_max_12bit_constraint_flag = 0;
+ general_max_10bit_constraint_flag = 0;
+ general_max_8bit_constraint_flag = 0;
+ general_max_422chroma_constraint_flag = 0;
+ general_max_420chroma_constraint_flag = 0;
+ general_max_monochrome_constraint_flag = 0;
+ general_intra_constraint_flag = 0;
+ general_one_picture_only_constraint_flag = 0;
+ general_lower_bit_rate_constraint_flag = 0;
+ general_max_14bit_constraint_flag = 0;
+ general_reserved_zero_7bits = 0;
+ general_reserved_zero_33bits = 0;
+ general_reserved_zero_34bits = 0;
+ general_reserved_zero_35bits = 0;
+ general_reserved_zero_43bits = 0;
+ general_inbld_flag = 0;
+ general_reserved_zero_bit = 0;
+ general_level_idc = 0;
+ memset(reserved_zero_2bits, 0, 8);
+}
+
+SrsHevcProfileTierLevel::~SrsHevcProfileTierLevel()
+{
+}
+
+// Parse the hevc vps/sps/pps
+srs_error_t SrsFormat::hevc_demux_hvcc(SrsBuffer *stream)
+{
+ srs_error_t err = srs_success;
+
+ int avc_extra_size = stream->size() - stream->pos();
+ if (avc_extra_size > 0) {
+ char *copy_stream_from = stream->data() + stream->pos();
+ vcodec->avc_extra_data = std::vector(copy_stream_from, copy_stream_from + avc_extra_size);
+ }
+
+ const int HEVC_MIN_SIZE = 23; // From configuration_version to numOfArrays
+ if (!stream->require(HEVC_MIN_SIZE)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires %d only %d bytes", HEVC_MIN_SIZE, stream->left());
+ }
+
+ SrsHevcDecoderConfigurationRecord *dec_conf_rec_p = &(vcodec->hevc_dec_conf_record_);
+ dec_conf_rec_p->configuration_version = stream->read_1bytes();
+ if (dec_conf_rec_p->configuration_version != 1) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "invalid version=%d", dec_conf_rec_p->configuration_version);
+ }
+
+ // Read general_profile_space(2bits), general_tier_flag(1bit), general_profile_idc(5bits)
+ uint8_t data_byte = stream->read_1bytes();
+ dec_conf_rec_p->general_profile_space = (data_byte >> 6) & 0x03;
+ dec_conf_rec_p->general_tier_flag = (data_byte >> 5) & 0x01;
+ dec_conf_rec_p->general_profile_idc = data_byte & 0x1F;
+ srs_info("hevc version:%d, general_profile_space:%d, general_tier_flag:%d, general_profile_idc:%d",
+ dec_conf_rec_p->configuration_version, dec_conf_rec_p->general_profile_space, dec_conf_rec_p->general_tier_flag,
+ dec_conf_rec_p->general_profile_idc);
+
+ // general_profile_compatibility_flags: 32bits
+ dec_conf_rec_p->general_profile_compatibility_flags = (uint32_t)stream->read_4bytes();
+
+ // general_constraint_indicator_flags: 48bits
+ uint64_t data_64bit = (uint64_t)stream->read_4bytes();
+ data_64bit = (data_64bit << 16) | (stream->read_2bytes());
+ dec_conf_rec_p->general_constraint_indicator_flags = data_64bit;
+
+ // general_level_idc: 8bits
+ dec_conf_rec_p->general_level_idc = stream->read_1bytes();
+ // min_spatial_segmentation_idc: xxxx 14bits
+ dec_conf_rec_p->min_spatial_segmentation_idc = stream->read_2bytes() & 0x0fff;
+ // parallelism_type: xxxx xx 2bits
+ dec_conf_rec_p->parallelism_type = stream->read_1bytes() & 0x03;
+ // chroma_format: xxxx xx 2bits
+ dec_conf_rec_p->chroma_format = stream->read_1bytes() & 0x03;
+ // bit_depth_luma_minus8: xxxx x 3bits
+ dec_conf_rec_p->bit_depth_luma_minus8 = stream->read_1bytes() & 0x07;
+ // bit_depth_chroma_minus8: xxxx x 3bits
+ dec_conf_rec_p->bit_depth_chroma_minus8 = stream->read_1bytes() & 0x07;
+ srs_info("general_constraint_indicator_flags:0x%x, general_level_idc:%d, min_spatial_segmentation_idc:%d, parallelism_type:%d, chroma_format:%d, bit_depth_luma_minus8:%d, bit_depth_chroma_minus8:%d",
+ dec_conf_rec_p->general_constraint_indicator_flags, dec_conf_rec_p->general_level_idc,
+ dec_conf_rec_p->min_spatial_segmentation_idc, dec_conf_rec_p->parallelism_type, dec_conf_rec_p->chroma_format,
+ dec_conf_rec_p->bit_depth_luma_minus8, dec_conf_rec_p->bit_depth_chroma_minus8);
+
+ // avg_frame_rate: 16bits
+ vcodec->frame_rate = dec_conf_rec_p->avg_frame_rate = stream->read_2bytes();
+ // 8bits: constant_frame_rate(2bits), num_temporal_layers(3bits),
+ // temporal_id_nested(1bit), length_size_minus_one(2bits)
+ data_byte = stream->read_1bytes();
+ dec_conf_rec_p->constant_frame_rate = (data_byte >> 6) & 0x03;
+ dec_conf_rec_p->num_temporal_layers = (data_byte >> 3) & 0x07;
+ dec_conf_rec_p->temporal_id_nested = (data_byte >> 2) & 0x01;
+
+ // Parse the NALU size.
+ dec_conf_rec_p->length_size_minus_one = data_byte & 0x03;
+ vcodec->NAL_unit_length = dec_conf_rec_p->length_size_minus_one;
+
+ // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
+ // 5.2.4.1 AVC decoder configuration record
+ // 5.2.4.1.2 Semantics
+ // The value of this field shall be one of 0, 1, or 3 corresponding to a
+ // length encoded with 1, 2, or 4 bytes, respectively.
+ if (vcodec->NAL_unit_length == 2) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2");
+ }
+
+ uint8_t numOfArrays = stream->read_1bytes();
+ srs_info("avg_frame_rate:%d, constant_frame_rate:%d, num_temporal_layers:%d, temporal_id_nested:%d, length_size_minus_one:%d, numOfArrays:%d",
+ dec_conf_rec_p->avg_frame_rate, dec_conf_rec_p->constant_frame_rate, dec_conf_rec_p->num_temporal_layers,
+ dec_conf_rec_p->temporal_id_nested, dec_conf_rec_p->length_size_minus_one, numOfArrays);
+
+ // parse vps/pps/sps
+ dec_conf_rec_p->nalu_vec.clear();
+ for (int index = 0; index < numOfArrays; index++) {
+ if (!stream->require(3)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires 3 only %d bytes", stream->left());
+ }
+ data_byte = stream->read_1bytes();
+
+ SrsHevcHvccNalu hevc_unit;
+ hevc_unit.array_completeness = (data_byte >> 7) & 0x01;
+ hevc_unit.nal_unit_type = data_byte & 0x3f;
+ hevc_unit.num_nalus = stream->read_2bytes();
+
+ for (int i = 0; i < hevc_unit.num_nalus; i++) {
+ if (!stream->require(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "num_nalus requires 2 only %d bytes", stream->left());
+ }
+
+ SrsHevcNalData data_item;
+ data_item.nal_unit_length = stream->read_2bytes();
+
+ if (!stream->require(data_item.nal_unit_length)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "requires %d only %d bytes",
+ data_item.nal_unit_length, stream->left());
+ }
+ // copy vps/pps/sps data
+ data_item.nal_unit_data.resize(data_item.nal_unit_length);
+
+ stream->read_bytes((char *)(&data_item.nal_unit_data[0]), data_item.nal_unit_length);
+ srs_info("hevc nalu type:%d, array_completeness:%d, num_nalus:%d, i:%d, nal_unit_length:%d",
+ hevc_unit.nal_unit_type, hevc_unit.array_completeness, hevc_unit.num_nalus, i, data_item.nal_unit_length);
+ hevc_unit.nal_data_vec.push_back(data_item);
+ }
+ dec_conf_rec_p->nalu_vec.push_back(hevc_unit);
+
+ // demux nalu
+ if ((err = hevc_demux_vps_sps_pps(&hevc_unit)) != srs_success) {
+ return srs_error_wrap(err, "hevc demux vps/sps/pps failed");
+ }
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::hevc_demux_vps_sps_pps(SrsHevcHvccNalu *nal)
+{
+ srs_error_t err = srs_success;
+
+ if (nal->nal_data_vec.empty()) {
+ return err;
+ }
+
+ // TODO: FIXME: Support for multiple VPS/SPS/PPS, then pick the first non-empty one.
+ char *frame = (char *)(&nal->nal_data_vec[0].nal_unit_data[0]);
+ int nb_frame = nal->nal_data_vec[0].nal_unit_length;
+ SrsBuffer stream(frame, nb_frame);
+
+ // nal data
+ switch (nal->nal_unit_type) {
+ case SrsHevcNaluType_VPS:
+ err = hevc_demux_vps(&stream);
+ break;
+ case SrsHevcNaluType_SPS:
+ err = hevc_demux_sps(&stream);
+ break;
+ case SrsHevcNaluType_PPS:
+ err = hevc_demux_pps(&stream);
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::hevc_demux_vps(SrsBuffer *stream)
+{
+ // for NALU, ITU-T H.265 7.3.2.1 Video parameter set RBSP syntax
+ // @see 7.3.1.2 NAL unit header syntax
+ // @doc ITU-T-H.265-2021.pdf, page 53.
+
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc vps requires 1 only %d bytes", stream->left());
+ }
+ int8_t nutv = stream->read_1bytes();
+
+ // forbidden_zero_bit shall be equal to 0.
+ int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
+ if (forbidden_zero_bit) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit);
+ }
+
+ // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
+ // @see 7.4.2.2 NAL unit header semantics
+ // @doc ITU-T-H.265-2021.pdf, page 86.
+ SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f);
+ if (nal_unit_type != SrsHevcNaluType_VPS) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc vps nal_unit_type=%d shall be equal to 33", nal_unit_type);
+ }
+
+ // nuh_layer_id + nuh_temporal_id_plus1
+ stream->skip(1);
+
+ // decode the rbsp from vps.
+ // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
+ std::vector rbsp(stream->size());
+
+ int nb_rbsp = srs_rbsp_remove_emulation_bytes(stream, rbsp);
+
+ return hevc_demux_vps_rbsp((char *)&rbsp[0], nb_rbsp);
+}
+
+srs_error_t SrsFormat::hevc_demux_vps_rbsp(char *rbsp, int nb_rbsp)
+{
+ srs_error_t err = srs_success;
+
+ // reparse the rbsp.
+ SrsBuffer stream(rbsp, nb_rbsp);
+
+ // H265 VPS (video_parameter_set_rbsp()) NAL Unit.
+ // Section 7.3.2.1 ("Video parameter set RBSP syntax") of the H.265
+ // ITU-T-H.265-2021.pdf, page 54.
+ if (!stream.require(4)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "vps requires 4 only %d bytes", stream.left());
+ }
+
+ SrsBitBuffer bs(&stream);
+
+ // vps_video_parameter_set_id u(4)
+ int vps_video_parameter_set_id = bs.read_bits(4);
+ if (vps_video_parameter_set_id < 0 || vps_video_parameter_set_id > SrsHevcMax_VPS_COUNT) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "vps id out of range: %d", vps_video_parameter_set_id);
+ }
+
+ // select table
+ SrsHevcDecoderConfigurationRecord *dec_conf_rec = &(vcodec->hevc_dec_conf_record_);
+ SrsHevcRbspVps *vps = &(dec_conf_rec->vps_table[vps_video_parameter_set_id]);
+
+ vps->vps_video_parameter_set_id = vps_video_parameter_set_id;
+ // vps_base_layer_internal_flag u(1)
+ vps->vps_base_layer_internal_flag = bs.read_bit();
+ // vps_base_layer_available_flag u(1)
+ vps->vps_base_layer_available_flag = bs.read_bit();
+ // vps_max_layers_minus1 u(6)
+ vps->vps_max_layers_minus1 = bs.read_bits(6);
+ // vps_max_sub_layers_minus1 u(3)
+ vps->vps_max_sub_layers_minus1 = bs.read_bits(3);
+ // vps_temporal_id_nesting_flag u(1)
+ vps->vps_temporal_id_nesting_flag = bs.read_bit();
+ // vps_reserved_0xffff_16bits u(16)
+ vps->vps_reserved_0xffff_16bits = bs.read_bits(16);
+
+ // profile_tier_level(1, vps_max_sub_layers_minus1)
+ if ((err = hevc_demux_rbsp_ptl(&bs, &vps->ptl, 1, vps->vps_max_sub_layers_minus1)) != srs_success) {
+ return srs_error_wrap(err, "vps rbsp ptl vps_max_sub_layers_minus1=%d", vps->vps_max_sub_layers_minus1);
+ }
+
+ dec_conf_rec->general_profile_idc = vps->ptl.general_profile_idc;
+ dec_conf_rec->general_level_idc = vps->ptl.general_level_idc;
+ dec_conf_rec->general_tier_flag = vps->ptl.general_tier_flag;
+
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sublayer flag requires 1 only %d bits", bs.left_bits());
+ }
+
+ // vps_sub_layer_ordering_info_present_flag u(1)
+ vps->vps_sub_layer_ordering_info_present_flag = bs.read_bit();
+
+ for (int i = (vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_sub_layers_minus1);
+ i <= vps->vps_max_sub_layers_minus1; i++) {
+ // vps_max_dec_pic_buffering_minus1[i] ue(v)
+ if ((err = bs.read_bits_ue(vps->vps_max_dec_pic_buffering_minus1[i])) != srs_success) {
+ return srs_error_wrap(err, "max_dec_pic_buffering_minus1");
+ }
+ // vps_max_num_reorder_pics[i] ue(v)
+ if ((err = bs.read_bits_ue(vps->vps_max_num_reorder_pics[i])) != srs_success) {
+ return srs_error_wrap(err, "max_num_reorder_pics");
+ }
+ // vps_max_latency_increase_plus1[i] ue(v)
+ if ((err = bs.read_bits_ue(vps->vps_max_latency_increase_plus1[i])) != srs_success) {
+ return srs_error_wrap(err, "max_latency_increase_plus1");
+ }
+ }
+
+ if (!bs.require_bits(6)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "vps maxlayer requires 10 only %d bits", bs.left_bits());
+ }
+
+ // vps_max_layer_id u(6)
+ vps->vps_max_layer_id = bs.read_bits(6);
+
+ // vps_num_layer_sets_minus1 ue(v)
+ if ((err = bs.read_bits_ue(vps->vps_num_layer_sets_minus1)) != srs_success) {
+ return srs_error_wrap(err, "num_layer_sets_minus1");
+ }
+
+ // TODO: FIXME: Implements it, you might parse remain bits for video_parameter_set_rbsp.
+ // @see 7.3.2.1 Video parameter set RBSP
+ // @doc ITU-T-H.265-2021.pdf, page 54.
+
+ return err;
+}
+
+srs_error_t SrsFormat::hevc_demux_sps(SrsBuffer *stream)
+{
+ // for NALU, ITU-T H.265 7.3.2.2 Sequence parameter set RBSP syntax
+ // @see 7.3.2.2.1 General sequence parameter set RBSP syntax
+ // @doc ITU-T-H.265-2021.pdf, page 55.
+
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc sps requires 1 only %d bytes", stream->left());
+ }
+ int8_t nutv = stream->read_1bytes();
+
+ // forbidden_zero_bit shall be equal to 0.
+ int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
+ if (forbidden_zero_bit) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit);
+ }
+
+ // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
+ // @see 7.4.2.2 NAL unit header semantics
+ // @doc ITU-T-H.265-2021.pdf, page 86.
+ SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f);
+ if (nal_unit_type != SrsHevcNaluType_SPS) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc sps nal_unit_type=%d shall be equal to 33", nal_unit_type);
+ }
+
+ // nuh_layer_id + nuh_temporal_id_plus1
+ stream->skip(1);
+
+ // decode the rbsp from sps.
+ // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
+ std::vector rbsp(stream->size());
+
+ int nb_rbsp = srs_rbsp_remove_emulation_bytes(stream, rbsp);
+
+ return hevc_demux_sps_rbsp((char *)&rbsp[0], nb_rbsp);
+}
+
+srs_error_t SrsFormat::hevc_demux_sps_rbsp(char *rbsp, int nb_rbsp)
+{
+ srs_error_t err = srs_success;
+
+ // we donot parse the detail of sps.
+ // @see https://github.com/ossrs/srs/issues/474
+ if (!avc_parse_sps) {
+ return err;
+ }
+
+ // reparse the rbsp.
+ SrsBuffer stream(rbsp, nb_rbsp);
+
+ // H265 SPS Nal Unit (seq_parameter_set_rbsp()) parser.
+ // Section 7.3.2.2 ("Sequence parameter set RBSP syntax") of the H.265
+ // ITU-T-H.265-2021.pdf, page 55.
+ if (!stream.require(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps requires 2 only %d bytes", stream.left());
+ }
+ uint8_t nutv = stream.read_1bytes();
+
+ // sps_video_parameter_set_id u(4)
+ int sps_video_parameter_set_id = (nutv >> 4) & 0x0f;
+ // sps_max_sub_layers_minus1 u(3)
+ int sps_max_sub_layers_minus1 = (nutv >> 1) & 0x07;
+ // sps_temporal_id_nesting_flag u(1)
+ int sps_temporal_id_nesting_flag = nutv & 0x01;
+
+ SrsBitBuffer bs(&stream);
+
+ // profile tier level...
+ SrsHevcProfileTierLevel profile_tier_level;
+ // profile_tier_level(1, sps_max_sub_layers_minus1)
+ if ((err = hevc_demux_rbsp_ptl(&bs, &profile_tier_level, 1, sps_max_sub_layers_minus1)) != srs_success) {
+ return srs_error_wrap(err, "sps rbsp ptl sps_max_sub_layers_minus1=%d", sps_max_sub_layers_minus1);
+ }
+
+ vcodec->hevc_profile = (SrsHevcProfile)profile_tier_level.general_profile_idc;
+ vcodec->hevc_level = (SrsHevcLevel)profile_tier_level.general_level_idc;
+
+ // sps_seq_parameter_set_id ue(v)
+ uint32_t sps_seq_parameter_set_id = 0;
+ if ((err = bs.read_bits_ue(sps_seq_parameter_set_id)) != srs_success) {
+ return srs_error_wrap(err, "sps_seq_parameter_set_id");
+ }
+ if (sps_seq_parameter_set_id < 0 || sps_seq_parameter_set_id >= SrsHevcMax_SPS_COUNT) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "sps id out of range: %d", sps_seq_parameter_set_id);
+ }
+
+ // for sps_table
+ SrsHevcDecoderConfigurationRecord *dec_conf_rec = &(vcodec->hevc_dec_conf_record_);
+ SrsHevcRbspSps *sps = &(dec_conf_rec->sps_table[sps_seq_parameter_set_id]);
+
+ sps->sps_video_parameter_set_id = sps_video_parameter_set_id;
+ sps->sps_max_sub_layers_minus1 = sps_max_sub_layers_minus1;
+ sps->sps_temporal_id_nesting_flag = sps_temporal_id_nesting_flag;
+ sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id;
+ sps->ptl = profile_tier_level;
+
+ // chroma_format_idc ue(v)
+ if ((err = bs.read_bits_ue(sps->chroma_format_idc)) != srs_success) {
+ return srs_error_wrap(err, "chroma_format_idc");
+ }
+
+ if (sps->chroma_format_idc == 3) {
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "separate_colour_plane_flag requires 1 only %d bits", bs.left_bits());
+ }
+
+ // separate_colour_plane_flag u(1)
+ sps->separate_colour_plane_flag = bs.read_bit();
+ }
+
+ // pic_width_in_luma_samples ue(v)
+ if ((err = bs.read_bits_ue(sps->pic_width_in_luma_samples)) != srs_success) {
+ return srs_error_wrap(err, "pic_width_in_luma_samples");
+ }
+
+ // pic_height_in_luma_samples ue(v)
+ if ((err = bs.read_bits_ue(sps->pic_height_in_luma_samples)) != srs_success) {
+ return srs_error_wrap(err, "pic_height_in_luma_samples");
+ }
+
+ vcodec->width = sps->pic_width_in_luma_samples;
+ vcodec->height = sps->pic_height_in_luma_samples;
+
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "conformance_window_flag requires 1 only %d bits", bs.left_bits());
+ }
+
+ // conformance_window_flag u(1)
+ sps->conformance_window_flag = bs.read_bit();
+ if (sps->conformance_window_flag) {
+ // conf_win_left_offset ue(v)
+ if ((err = bs.read_bits_ue(sps->conf_win_left_offset)) != srs_success) {
+ return srs_error_wrap(err, "conf_win_left_offset");
+ }
+ // conf_win_right_offset ue(v)
+ if ((err = bs.read_bits_ue(sps->conf_win_right_offset)) != srs_success) {
+ return srs_error_wrap(err, "conf_win_right_offset");
+ }
+ // conf_win_top_offset ue(v)
+ if ((err = bs.read_bits_ue(sps->conf_win_top_offset)) != srs_success) {
+ return srs_error_wrap(err, "conf_win_top_offset");
+ }
+ // conf_win_bottom_offset ue(v)
+ if ((err = bs.read_bits_ue(sps->conf_win_bottom_offset)) != srs_success) {
+ return srs_error_wrap(err, "conf_win_bottom_offset");
+ }
+
+ // Table 6-1, 7.4.3.2.1
+ // ITU-T-H.265-2021.pdf, page 42.
+ // Recalculate width and height
+ // Note: 1 is added to the manual, but it is not actually used
+ // https://gitlab.com/mbunkus/mkvtoolnix/-/issues/1152
+ int sub_width_c = ((1 == sps->chroma_format_idc) || (2 == sps->chroma_format_idc)) && (0 == sps->separate_colour_plane_flag) ? 2 : 1;
+ int sub_height_c = (1 == sps->chroma_format_idc) && (0 == sps->separate_colour_plane_flag) ? 2 : 1;
+ vcodec->width -= (sub_width_c * sps->conf_win_right_offset + sub_width_c * sps->conf_win_left_offset);
+ vcodec->height -= (sub_height_c * sps->conf_win_bottom_offset + sub_height_c * sps->conf_win_top_offset);
+ }
+
+ // bit_depth_luma_minus8 ue(v)
+ if ((err = bs.read_bits_ue(sps->bit_depth_luma_minus8)) != srs_success) {
+ return srs_error_wrap(err, "bit_depth_luma_minus8");
+ }
+ // bit_depth_chroma_minus8 ue(v)
+ if ((err = bs.read_bits_ue(sps->bit_depth_chroma_minus8)) != srs_success) {
+ return srs_error_wrap(err, "bit_depth_chroma_minus8");
+ }
+
+ // bit depth
+ dec_conf_rec->bit_depth_luma_minus8 = sps->bit_depth_luma_minus8 + 8;
+ dec_conf_rec->bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8 + 8;
+
+ // log2_max_pic_order_cnt_lsb_minus4 ue(v)
+ if ((err = bs.read_bits_ue(sps->log2_max_pic_order_cnt_lsb_minus4)) != srs_success) {
+ return srs_error_wrap(err, "log2_max_pic_order_cnt_lsb_minus4");
+ }
+
+ // TODO: FIXME: Implements it, you might parse remain bits for seq_parameter_set_rbsp.
+ // 7.3.2.2 Sequence parameter set RBSP syntax
+ // ITU-T-H.265-2021.pdf, page 55 ~ page 57.
+
+ // 7.3.2.11 RBSP trailing bits syntax
+ // ITU-T-H.265-2021.pdf, page 61.
+ // rbsp_trailing_bits()
+
+ return err;
+}
+
+srs_error_t SrsFormat::hevc_demux_pps(SrsBuffer *stream)
+{
+ // for NALU, ITU-T H.265 7.3.2.3 Picture parameter set RBSP syntax
+ // @see 7.3.2.3 Picture parameter set RBSP syntax
+ // @doc ITU-T-H.265-2021.pdf, page 57.
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "decode hevc pps requires 1 only %d bytes", stream->left());
+ }
+ int8_t nutv = stream->read_1bytes();
+
+ // forbidden_zero_bit shall be equal to 0.
+ int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
+ if (forbidden_zero_bit) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc forbidden_zero_bit=%d shall be equal to 0", forbidden_zero_bit);
+ }
+
+ // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
+ // @see 7.4.2.2 NAL unit header semantics
+ // @doc ITU-T-H.265-2021.pdf, page 86.
+ SrsHevcNaluType nal_unit_type = (SrsHevcNaluType)((nutv >> 1) & 0x3f);
+ if (nal_unit_type != SrsHevcNaluType_PPS) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "hevc pps nal_unit_type=%d shall be equal to 33", nal_unit_type);
+ }
+
+ // nuh_layer_id + nuh_temporal_id_plus1
+ stream->skip(1);
+
+ // decode the rbsp from pps.
+ // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
+ std::vector rbsp(stream->size());
+
+ int nb_rbsp = srs_rbsp_remove_emulation_bytes(stream, rbsp);
+
+ return hevc_demux_pps_rbsp((char *)&rbsp[0], nb_rbsp);
+}
+
+srs_error_t SrsFormat::hevc_demux_pps_rbsp(char *rbsp, int nb_rbsp)
+{
+ srs_error_t err = srs_success;
+
+ // reparse the rbsp.
+ SrsBuffer stream(rbsp, nb_rbsp);
+
+ // H265 PPS NAL Unit (pic_parameter_set_rbsp()) parser.
+ // Section 7.3.2.3 ("Picture parameter set RBSP syntax") of the H.265
+ // ITU-T-H.265-2021.pdf, page 57.
+ SrsBitBuffer bs(&stream);
+
+ // pps_pic_parameter_set_id ue(v)
+ uint32_t pps_pic_parameter_set_id = 0;
+ if ((err = bs.read_bits_ue(pps_pic_parameter_set_id)) != srs_success) {
+ return srs_error_wrap(err, "pps_pic_parameter_set_id");
+ }
+ if (pps_pic_parameter_set_id < 0 || pps_pic_parameter_set_id >= SrsHevcMax_PPS_COUNT) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps id out of range: %d", pps_pic_parameter_set_id);
+ }
+
+ // select table
+ SrsHevcDecoderConfigurationRecord *dec_conf_rec = &(vcodec->hevc_dec_conf_record_);
+ SrsHevcRbspPps *pps = &(dec_conf_rec->pps_table[pps_pic_parameter_set_id]);
+ pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id;
+
+ // pps_seq_parameter_set_id ue(v)
+ uint32_t pps_seq_parameter_set_id = 0;
+ if ((err = bs.read_bits_ue(pps_seq_parameter_set_id)) != srs_success) {
+ return srs_error_wrap(err, "pps_seq_parameter_set_id");
+ }
+ pps->pps_seq_parameter_set_id = pps_seq_parameter_set_id;
+
+ if (!bs.require_bits(7)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps slice requires 7 only %d bits", bs.left_bits());
+ }
+
+ // dependent_slice_segments_enabled_flag u(1)
+ pps->dependent_slice_segments_enabled_flag = bs.read_bit();
+ // output_flag_present_flag u(1)
+ pps->output_flag_present_flag = bs.read_bit();
+ // num_extra_slice_header_bits u(3)
+ pps->num_extra_slice_header_bits = bs.read_bits(3);
+ // sign_data_hiding_enabled_flag u(1)
+ pps->sign_data_hiding_enabled_flag = bs.read_bit();
+ // cabac_init_present_flag u(1)
+ pps->cabac_init_present_flag = bs.read_bit();
+
+ // num_ref_idx_l0_default_active_minus1 ue(v)
+ if ((err = bs.read_bits_ue(pps->num_ref_idx_l0_default_active_minus1)) != srs_success) {
+ return srs_error_wrap(err, "num_ref_idx_l0_default_active_minus1");
+ }
+ // num_ref_idx_l1_default_active_minus1 ue(v)
+ if ((err = bs.read_bits_ue(pps->num_ref_idx_l1_default_active_minus1)) != srs_success) {
+ return srs_error_wrap(err, "num_ref_idx_l1_default_active_minus1");
+ }
+ // init_qp_minus26 se(v)
+ if ((err = bs.read_bits_se(pps->init_qp_minus26)) != srs_success) {
+ return srs_error_wrap(err, "init_qp_minus26");
+ }
+
+ if (!bs.require_bits(3)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps requires 3 only %d bits", bs.left_bits());
+ }
+
+ // constrained_intra_pred_flag u(1)
+ pps->constrained_intra_pred_flag = bs.read_bit();
+ // transform_skip_enabled_flag u(1)
+ pps->transform_skip_enabled_flag = bs.read_bit();
+ // cu_qp_delta_enabled_flag u(1)
+ pps->cu_qp_delta_enabled_flag = bs.read_bit();
+ if (pps->cu_qp_delta_enabled_flag) {
+ // diff_cu_qp_delta_depth ue(v)
+ if ((err = bs.read_bits_ue(pps->diff_cu_qp_delta_depth)) != srs_success) {
+ return srs_error_wrap(err, "diff_cu_qp_delta_depth");
+ }
+ }
+ // pps_cb_qp_offset se(v)
+ if ((err = bs.read_bits_se(pps->pps_cb_qp_offset)) != srs_success) {
+ return srs_error_wrap(err, "pps_cb_qp_offset");
+ }
+ // pps_cr_qp_offset se(v)
+ if ((err = bs.read_bits_se(pps->pps_cr_qp_offset)) != srs_success) {
+ return srs_error_wrap(err, "pps_cr_qp_offset");
+ }
+
+ if (!bs.require_bits(6)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps slice_chroma_qp requires 6 only %d bits", bs.left_bits());
+ }
+
+ // pps_slice_chroma_qp_offsets_present_flag u(1)
+ pps->pps_slice_chroma_qp_offsets_present_flag = bs.read_bit();
+ // weighted_pred_flag u(1)
+ pps->weighted_pred_flag = bs.read_bit();
+ // weighted_bipred_flag u(1)
+ pps->weighted_bipred_flag = bs.read_bit();
+ // transquant_bypass_enabled_flag u(1)
+ pps->transquant_bypass_enabled_flag = bs.read_bit();
+ // tiles_enabled_flag u(1)
+ pps->tiles_enabled_flag = bs.read_bit();
+ // entropy_coding_sync_enabled_flag u(1)
+ pps->entropy_coding_sync_enabled_flag = bs.read_bit();
+
+ if (pps->tiles_enabled_flag) {
+ // num_tile_columns_minus1 ue(v)
+ if ((err = bs.read_bits_ue(pps->num_tile_columns_minus1)) != srs_success) {
+ return srs_error_wrap(err, "num_tile_columns_minus1");
+ }
+ // num_tile_rows_minus1 ue(v)
+ if ((err = bs.read_bits_ue(pps->num_tile_rows_minus1)) != srs_success) {
+ return srs_error_wrap(err, "num_tile_rows_minus1");
+ }
+
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "uniform_spacing_flag requires 1 only %d bits", bs.left_bits());
+ }
+
+ // uniform_spacing_flag u(1)
+ pps->uniform_spacing_flag = bs.read_bit();
+ if (!pps->uniform_spacing_flag) {
+ pps->column_width_minus1.resize(pps->num_tile_columns_minus1);
+ pps->row_height_minus1.resize(pps->num_tile_rows_minus1);
+
+ for (int i = 0; i < (int)pps->num_tile_columns_minus1; i++) {
+ // column_width_minus1[i] ue(v)
+ if ((err = bs.read_bits_ue(pps->column_width_minus1[i])) != srs_success) {
+ return srs_error_wrap(err, "column_width_minus1");
+ }
+ }
+
+ for (int i = 0; i < (int)pps->num_tile_rows_minus1; i++) {
+ // row_height_minus1[i] ue(v)
+ if ((err = bs.read_bits_ue(pps->row_height_minus1[i])) != srs_success) {
+ return srs_error_wrap(err, "row_height_minus1");
+ }
+ }
+ }
+
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "loop_filter_across_tiles_enabled_flag requires 1 only %d bits", bs.left_bits());
+ }
+
+ // loop_filter_across_tiles_enabled_flag u(1)
+ pps->loop_filter_across_tiles_enabled_flag = bs.read_bit();
+ }
+
+ if (!bs.require_bits(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps loop deblocking filter requires 2 only %d bits", bs.left_bits());
+ }
+
+ // pps_loop_filter_across_slices_enabled_flag u(1)
+ pps->pps_loop_filter_across_slices_enabled_flag = bs.read_bit();
+ // deblocking_filter_control_present_flag u(1)
+ pps->deblocking_filter_control_present_flag = bs.read_bit();
+ if (pps->deblocking_filter_control_present_flag) {
+ if (!bs.require_bits(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps loop deblocking filter flag requires 2 only %d bits", bs.left_bits());
+ }
+
+ // deblocking_filter_override_enabled_flag u(1)
+ pps->deblocking_filter_override_enabled_flag = bs.read_bit();
+ // pps_deblocking_filter_disabled_flag u(1)
+ pps->pps_deblocking_filter_disabled_flag = bs.read_bit();
+ if (!pps->pps_deblocking_filter_disabled_flag) {
+ // pps_beta_offset_div2 se(v)
+ if ((err = bs.read_bits_se(pps->pps_beta_offset_div2)) != srs_success) {
+ return srs_error_wrap(err, "pps_beta_offset_div2");
+ }
+ // pps_tc_offset_div2 se(v)
+ if ((err = bs.read_bits_se(pps->pps_tc_offset_div2)) != srs_success) {
+ return srs_error_wrap(err, "pps_tc_offset_div2");
+ }
+ }
+ }
+
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps scaling_list_data requires 1 only %d bits", bs.left_bits());
+ }
+
+ // pps_scaling_list_data_present_flag u(1)
+ pps->pps_scaling_list_data_present_flag = bs.read_bit();
+ if (pps->pps_scaling_list_data_present_flag) {
+ // 7.3.4 Scaling list data syntax
+ SrsHevcScalingListData *sld = &pps->scaling_list_data;
+ for (int sizeId = 0; sizeId < 4; sizeId++) {
+ for (int matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
+ // scaling_list_pred_mode_flag u(1)
+ sld->scaling_list_pred_mode_flag[sizeId][matrixId] = bs.read_bit();
+ if (!sld->scaling_list_pred_mode_flag[sizeId][matrixId]) {
+ // scaling_list_pred_matrix_id_delta ue(v)
+ if ((err = bs.read_bits_ue(sld->scaling_list_pred_matrix_id_delta[sizeId][matrixId])) != srs_success) {
+ return srs_error_wrap(err, "scaling_list_pred_matrix_id_delta");
+ }
+ } else {
+ int nextCoef = 8;
+ int coefNum = srs_min(64, (1 << (4 + (sizeId << 1))));
+ sld->coefNum = coefNum; // tmp store
+ if (sizeId > 1) {
+ // scaling_list_dc_coef_minus8 se(v)
+ if ((err = bs.read_bits_se(sld->scaling_list_dc_coef_minus8[sizeId - 2][matrixId])) != srs_success) {
+ return srs_error_wrap(err, "scaling_list_dc_coef_minus8");
+ }
+ nextCoef = sld->scaling_list_dc_coef_minus8[sizeId - 2][matrixId] + 8;
+ }
+
+ for (int i = 0; i < sld->coefNum; i++) {
+ // scaling_list_delta_coef se(v)
+ int scaling_list_delta_coef = 0;
+ if ((err = bs.read_bits_se(scaling_list_delta_coef)) != srs_success) {
+ return srs_error_wrap(err, "scaling_list_delta_coef");
+ }
+ nextCoef = (nextCoef + scaling_list_delta_coef + 256) % 256;
+ sld->ScalingList[sizeId][matrixId][i] = nextCoef;
+ }
+ }
+ }
+ }
+ }
+
+ if (!bs.require_bits(1)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "lists_modification_present_flag requires 1 only %d bits", bs.left_bits());
+ }
+ // lists_modification_present_flag u(1)
+ pps->lists_modification_present_flag = bs.read_bit();
+
+ // log2_parallel_merge_level_minus2 ue(v)
+ if ((err = bs.read_bits_ue(pps->log2_parallel_merge_level_minus2)) != srs_success) {
+ return srs_error_wrap(err, "log2_parallel_merge_level_minus2");
+ }
+
+ if (!bs.require_bits(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "extension_present_flag requires 2 only %d bits", bs.left_bits());
+ }
+
+ // slice_segment_header_extension_present_flag u(1)
+ pps->slice_segment_header_extension_present_flag = bs.read_bit();
+ // pps_extension_present_flag u(1)
+ pps->pps_extension_present_flag = bs.read_bit();
+ if (pps->pps_extension_present_flag) {
+ if (!bs.require_bits(8)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "pps_range_extension_flag requires 8 only %d bits", bs.left_bits());
+ }
+
+ // pps_range_extension_flag u(1)
+ pps->pps_range_extension_flag = bs.read_bit();
+ // pps_multilayer_extension_flag u(1)
+ pps->pps_multilayer_extension_flag = bs.read_bit();
+ // pps_3d_extension_flag u(1)
+ pps->pps_3d_extension_flag = bs.read_bit();
+ // pps_scc_extension_flag u(1)
+ pps->pps_scc_extension_flag = bs.read_bit();
+ // pps_extension_4bits u(4)
+ pps->pps_extension_4bits = bs.read_bits(4);
+ }
+
+ // TODO: FIXME: Implements it, you might parse remain bits for pic_parameter_set_rbsp.
+ // @see 7.3.2.3 Picture parameter set RBSP syntax
+ // @doc ITU-T-H.265-2021.pdf, page 59.
+
+ // TODO: FIXME: rbsp_trailing_bits
+
+ return err;
+}
+
+srs_error_t SrsFormat::hevc_demux_rbsp_ptl(SrsBitBuffer *bs, SrsHevcProfileTierLevel *ptl, int profile_present_flag, int max_sub_layers_minus1)
+{
+ srs_error_t err = srs_success;
+
+ // profile_tier_level() parser.
+ // Section 7.3.3 ("Profile, tier and level syntax") of the H.265
+ // ITU-T-H.265-2021.pdf, page 62.
+ if (profile_present_flag) {
+ if (!bs->require_bits(88)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl profile requires 88 only %d bits", bs->left_bits());
+ }
+
+ // profile_space u(2)
+ ptl->general_profile_space = bs->read_bits(2);
+ // tier_flag u(1)
+ ptl->general_tier_flag = bs->read_bit();
+ // profile_idc u(5)
+ ptl->general_profile_idc = bs->read_bits(5);
+ for (int i = 0; i < 32; i++) {
+ // profile_compatibility_flag[j] u(1)
+ ptl->general_profile_compatibility_flag[i] = bs->read_bit();
+ }
+ // progressive_source_flag u(1)
+ ptl->general_progressive_source_flag = bs->read_bit();
+ // interlaced_source_flag u(1)
+ ptl->general_interlaced_source_flag = bs->read_bit();
+ // non_packed_constraint_flag u(1)
+ ptl->general_non_packed_constraint_flag = bs->read_bit();
+ // frame_only_constraint_flag u(1)
+ ptl->general_frame_only_constraint_flag = bs->read_bit();
+ if (ptl->general_profile_idc == 4 || ptl->general_profile_compatibility_flag[4] ||
+ ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] ||
+ ptl->general_profile_idc == 6 || ptl->general_profile_compatibility_flag[6] ||
+ ptl->general_profile_idc == 7 || ptl->general_profile_compatibility_flag[7] ||
+ ptl->general_profile_idc == 8 || ptl->general_profile_compatibility_flag[8] ||
+ ptl->general_profile_idc == 9 || ptl->general_profile_compatibility_flag[9] ||
+ ptl->general_profile_idc == 10 || ptl->general_profile_compatibility_flag[10] ||
+ ptl->general_profile_idc == 11 || ptl->general_profile_compatibility_flag[11]) {
+ // The number of bits in this syntax structure is not affected by this condition
+ // max_12bit_constraint_flag u(1)
+ ptl->general_max_12bit_constraint_flag = bs->read_bit();
+ // max_10bit_constraint_flag u(1)
+ ptl->general_max_10bit_constraint_flag = bs->read_bit();
+ // max_8bit_constraint_flag u(1)
+ ptl->general_max_8bit_constraint_flag = bs->read_bit();
+ // max_422chroma_constraint_flag u(1)
+ ptl->general_max_422chroma_constraint_flag = bs->read_bit();
+ // max_420chroma_constraint_flag u(1)
+ ptl->general_max_420chroma_constraint_flag = bs->read_bit();
+ // max_monochrome_constraint_flag u(1)
+ ptl->general_max_monochrome_constraint_flag = bs->read_bit();
+ // intra_constraint_flag u(1)
+ ptl->general_intra_constraint_flag = bs->read_bit();
+ // one_picture_only_constraint_flag u(1)
+ ptl->general_one_picture_only_constraint_flag = bs->read_bit();
+ // lower_bit_rate_constraint_flag u(1)
+ ptl->general_lower_bit_rate_constraint_flag = bs->read_bit();
+
+ if (ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] == 1 ||
+ ptl->general_profile_idc == 9 || ptl->general_profile_compatibility_flag[9] == 1 ||
+ ptl->general_profile_idc == 10 || ptl->general_profile_compatibility_flag[10] == 1 ||
+ ptl->general_profile_idc == 11 || ptl->general_profile_compatibility_flag[11] == 1) {
+ // max_14bit_constraint_flag u(1)
+ ptl->general_max_14bit_constraint_flag = bs->read_bit();
+ // reserved_zero_33bits u(33)
+ uint32_t bits_tmp_hi = bs->read_bit();
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->general_reserved_zero_33bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ } else {
+ // reserved_zero_34bits u(34)
+ uint32_t bits_tmp_hi = bs->read_bits(2);
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->general_reserved_zero_34bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ }
+ } else if (ptl->general_profile_idc == 2 || ptl->general_profile_compatibility_flag[2]) {
+ // general_reserved_zero_7bits u(7)
+ ptl->general_reserved_zero_7bits = bs->read_bits(7);
+ // general_one_picture_only_constraint_flag u(1)
+ ptl->general_one_picture_only_constraint_flag = bs->read_bit();
+ // general_reserved_zero_35bits u(35)
+ uint32_t bits_tmp_hi = bs->read_bits(3);
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->general_reserved_zero_35bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ } else {
+ // reserved_zero_43bits u(43)
+ uint32_t bits_tmp_hi = bs->read_bits(11);
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->general_reserved_zero_43bits = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ }
+
+ // The number of bits in this syntax structure is not affected by this condition
+ if (ptl->general_profile_idc == 1 || ptl->general_profile_compatibility_flag[1] ||
+ ptl->general_profile_idc == 2 || ptl->general_profile_compatibility_flag[2] ||
+ ptl->general_profile_idc == 3 || ptl->general_profile_compatibility_flag[3] ||
+ ptl->general_profile_idc == 4 || ptl->general_profile_compatibility_flag[4] ||
+ ptl->general_profile_idc == 5 || ptl->general_profile_compatibility_flag[5] ||
+ ptl->general_profile_idc == 9 || ptl->general_profile_compatibility_flag[9] ||
+ ptl->general_profile_idc == 11 || ptl->general_profile_compatibility_flag[11]) {
+ // inbld_flag u(1)
+ ptl->general_inbld_flag = bs->read_bit();
+ } else {
+ // reserved_zero_bit u(1)
+ ptl->general_reserved_zero_bit = bs->read_bit();
+ }
+ }
+
+ if (!bs->require_bits(8)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl level requires 8 only %d bits", bs->left_bits());
+ }
+
+ // general_level_idc u(8)
+ ptl->general_level_idc = bs->read_8bits();
+
+ ptl->sub_layer_profile_present_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_level_present_flag.resize(max_sub_layers_minus1);
+ for (int i = 0; i < max_sub_layers_minus1; i++) {
+ if (!bs->require_bits(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl present_flag requires 2 only %d bits", bs->left_bits());
+ }
+ // sub_layer_profile_present_flag[i] u(1)
+ ptl->sub_layer_profile_present_flag[i] = bs->read_bit();
+ // sub_layer_level_present_flag[i] u(1)
+ ptl->sub_layer_level_present_flag[i] = bs->read_bit();
+ }
+
+ for (int i = max_sub_layers_minus1; max_sub_layers_minus1 > 0 && i < 8; i++) {
+ if (!bs->require_bits(2)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl reserved_zero requires 2 only %d bits", bs->left_bits());
+ }
+ // reserved_zero_2bits[i] u(2)
+ ptl->reserved_zero_2bits[i] = bs->read_bits(2);
+ }
+
+ ptl->sub_layer_profile_space.resize(max_sub_layers_minus1);
+ ptl->sub_layer_tier_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_profile_idc.resize(max_sub_layers_minus1);
+ ptl->sub_layer_profile_compatibility_flag.resize(max_sub_layers_minus1);
+ for (int i = 0; i < max_sub_layers_minus1; i++) {
+ ptl->sub_layer_profile_compatibility_flag[i].resize(32);
+ }
+ ptl->sub_layer_progressive_source_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_interlaced_source_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_non_packed_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_frame_only_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_max_12bit_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_max_10bit_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_max_8bit_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_max_422chroma_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_max_420chroma_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_max_monochrome_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_intra_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_one_picture_only_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_lower_bit_rate_constraint_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_reserved_zero_34bits.resize(max_sub_layers_minus1);
+ ptl->sub_layer_reserved_zero_43bits.resize(max_sub_layers_minus1);
+ ptl->sub_layer_inbld_flag.resize(max_sub_layers_minus1);
+ ptl->sub_layer_reserved_zero_bit.resize(max_sub_layers_minus1);
+ ptl->sub_layer_level_idc.resize(max_sub_layers_minus1);
+ for (int i = 0; i < max_sub_layers_minus1; i++) {
+ if (ptl->sub_layer_profile_present_flag[i]) {
+ if (!bs->require_bits(88)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl sub_layer_profile requires 88 only %d bits", bs->left_bits());
+ }
+ // profile_space u(2)
+ ptl->sub_layer_profile_space[i] = bs->read_bits(2);
+ // tier_flag u(1)
+ ptl->sub_layer_tier_flag[i] = bs->read_bit();
+ // profile_idc u(5)
+ ptl->sub_layer_profile_idc[i] = bs->read_bits(5);
+ for (int j = 0; j < 32; j++) {
+ // profile_compatibility_flag[j] u(1)
+ ptl->sub_layer_profile_compatibility_flag[i][j] = bs->read_bit();
+ }
+ // progressive_source_flag u(1)
+ ptl->sub_layer_progressive_source_flag[i] = bs->read_bit();
+ // interlaced_source_flag u(1)
+ ptl->sub_layer_interlaced_source_flag[i] = bs->read_bit();
+ // non_packed_constraint_flag u(1)
+ ptl->sub_layer_non_packed_constraint_flag[i] = bs->read_bit();
+ // frame_only_constraint_flag u(1)
+ ptl->sub_layer_frame_only_constraint_flag[i] = bs->read_bit();
+ if (ptl->sub_layer_profile_idc[i] == 4 || ptl->sub_layer_profile_compatibility_flag[i][4] ||
+ ptl->sub_layer_profile_idc[i] == 5 || ptl->sub_layer_profile_compatibility_flag[i][5] ||
+ ptl->sub_layer_profile_idc[i] == 6 || ptl->sub_layer_profile_compatibility_flag[i][6] ||
+ ptl->sub_layer_profile_idc[i] == 7 || ptl->sub_layer_profile_compatibility_flag[i][7] ||
+ ptl->sub_layer_profile_idc[i] == 8 || ptl->sub_layer_profile_compatibility_flag[i][8] ||
+ ptl->sub_layer_profile_idc[i] == 9 || ptl->sub_layer_profile_compatibility_flag[i][9] ||
+ ptl->sub_layer_profile_idc[i] == 10 || ptl->sub_layer_profile_compatibility_flag[i][10] ||
+ ptl->sub_layer_profile_idc[i] == 11 || ptl->sub_layer_profile_compatibility_flag[i][11]) {
+ // The number of bits in this syntax structure is not affected by this condition.
+ // max_12bit_constraint_flag u(1)
+ ptl->sub_layer_max_12bit_constraint_flag[i] = bs->read_bit();
+ // max_10bit_constraint_flag u(1)
+ ptl->sub_layer_max_10bit_constraint_flag[i] = bs->read_bit();
+ // max_8bit_constraint_flag u(1)
+ ptl->sub_layer_max_8bit_constraint_flag[i] = bs->read_bit();
+ // max_422chroma_constraint_flag u(1)
+ ptl->sub_layer_max_422chroma_constraint_flag[i] = bs->read_bit();
+ // max_420chroma_constraint_flag u(1)
+ ptl->sub_layer_max_420chroma_constraint_flag[i] = bs->read_bit();
+ // max_monochrome_constraint_flag u(1)
+ ptl->sub_layer_max_monochrome_constraint_flag[i] = bs->read_bit();
+ // intra_constraint_flag u(1)
+ ptl->sub_layer_intra_constraint_flag[i] = bs->read_bit();
+ // one_picture_only_constraint_flag u(1)
+ ptl->sub_layer_one_picture_only_constraint_flag[i] = bs->read_bit();
+ // lower_bit_rate_constraint_flag u(1)
+ ptl->sub_layer_lower_bit_rate_constraint_flag[i] = bs->read_bit();
+
+ if (ptl->sub_layer_profile_idc[i] == 5 ||
+ ptl->sub_layer_profile_compatibility_flag[i][5] == 1 ||
+ ptl->sub_layer_profile_idc[i] == 9 ||
+ ptl->sub_layer_profile_compatibility_flag[i][9] == 1 ||
+ ptl->sub_layer_profile_idc[i] == 10 ||
+ ptl->sub_layer_profile_compatibility_flag[i][10] == 1 ||
+ ptl->sub_layer_profile_idc[i] == 11 ||
+ ptl->sub_layer_profile_compatibility_flag[i][11] == 1) {
+ // max_14bit_constraint_flag u(1)
+ ptl->general_max_14bit_constraint_flag = bs->read_bit();
+ // reserved_zero_33bits u(33)
+ uint32_t bits_tmp_hi = bs->read_bit();
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->sub_layer_reserved_zero_33bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ } else {
+ // reserved_zero_34bits u(34)
+ uint32_t bits_tmp_hi = bs->read_bits(2);
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->sub_layer_reserved_zero_34bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ }
+ } else if (ptl->sub_layer_profile_idc[i] == 2 || ptl->sub_layer_profile_compatibility_flag[i][2]) {
+ // sub_layer_reserved_zero_7bits u(7)
+ ptl->sub_layer_reserved_zero_7bits[i] = bs->read_bits(7);
+ // sub_layer_one_picture_only_constraint_flag u(1)
+ ptl->sub_layer_one_picture_only_constraint_flag[i] = bs->read_bit();
+ // sub_layer_reserved_zero_35bits u(35)
+ uint32_t bits_tmp_hi = bs->read_bits(3);
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->sub_layer_reserved_zero_35bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ } else {
+ // reserved_zero_43bits u(43)
+ uint32_t bits_tmp_hi = bs->read_bits(11);
+ uint32_t bits_tmp = bs->read_bits(32);
+ ptl->sub_layer_reserved_zero_43bits[i] = ((uint64_t)bits_tmp_hi << 32) | bits_tmp;
+ }
+
+ // The number of bits in this syntax structure is not affected by this condition
+ if (ptl->sub_layer_profile_idc[i] == 1 || ptl->sub_layer_profile_compatibility_flag[i][1] ||
+ ptl->sub_layer_profile_idc[i] == 2 || ptl->sub_layer_profile_compatibility_flag[i][2] ||
+ ptl->sub_layer_profile_idc[i] == 3 || ptl->sub_layer_profile_compatibility_flag[i][3] ||
+ ptl->sub_layer_profile_idc[i] == 4 || ptl->sub_layer_profile_compatibility_flag[i][4] ||
+ ptl->sub_layer_profile_idc[i] == 5 || ptl->sub_layer_profile_compatibility_flag[i][5] ||
+ ptl->sub_layer_profile_idc[i] == 9 || ptl->sub_layer_profile_compatibility_flag[i][9] ||
+ ptl->sub_layer_profile_idc[i] == 11 || ptl->sub_layer_profile_compatibility_flag[i][11]) {
+ // inbld_flag u(1)
+ ptl->sub_layer_inbld_flag[i] = bs->read_bit();
+ } else {
+ // reserved_zero_bit u(1)
+ ptl->sub_layer_reserved_zero_bit[i] = bs->read_bit();
+ }
+ }
+
+ if (ptl->sub_layer_level_present_flag[i]) {
+ if (!bs->require_bits(8)) {
+ return srs_error_new(ERROR_HEVC_DECODE_ERROR, "ptl sub_layer_level requires 8 only %d bits", bs->left_bits());
+ }
+ // sub_layer_level_idc u(8)
+ ptl->sub_layer_level_idc[i] = bs->read_bits(8);
+ }
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer *stream)
+{
+ // AVCDecoderConfigurationRecord
+ // 5.2.4.1.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
+ int avc_extra_size = stream->size() - stream->pos();
+ if (avc_extra_size > 0) {
+ char *copy_stream_from = stream->data() + stream->pos();
+ vcodec->avc_extra_data = std::vector(copy_stream_from, copy_stream_from + avc_extra_size);
+ }
+
+ if (!stream->require(6)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode sequence header");
+ }
+ // int8_t configuration_version = stream->read_1bytes();
+ stream->read_1bytes();
+ // int8_t AVCProfileIndication = stream->read_1bytes();
+ vcodec->avc_profile = (SrsAvcProfile)stream->read_1bytes();
+ // int8_t profile_compatibility = stream->read_1bytes();
+ stream->read_1bytes();
+ // int8_t AVCLevelIndication = stream->read_1bytes();
+ vcodec->avc_level = (SrsAvcLevel)stream->read_1bytes();
+
+ // parse the NALU size.
+ int8_t lengthSizeMinusOne = stream->read_1bytes();
+ lengthSizeMinusOne &= 0x03;
+ vcodec->NAL_unit_length = lengthSizeMinusOne;
+
+ // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
+ // 5.2.4.1 AVC decoder configuration record
+ // 5.2.4.1.2 Semantics
+ // The value of this field shall be one of 0, 1, or 3 corresponding to a
+ // length encoded with 1, 2, or 4 bytes, respectively.
+ if (vcodec->NAL_unit_length == 2) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps lengthSizeMinusOne should never be 2");
+ }
+
+ // 1 sps, 7.3.2.1 Sequence parameter set RBSP syntax
+ // ISO_IEC_14496-10-AVC-2003.pdf, page 45.
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
+ }
+ int8_t numOfSequenceParameterSets = stream->read_1bytes();
+ numOfSequenceParameterSets &= 0x1f;
+ if (numOfSequenceParameterSets < 1) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
+ }
+ // Support for multiple SPS, then pick the first non-empty one.
+ for (int i = 0; i < numOfSequenceParameterSets; ++i) {
+ if (!stream->require(2)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size");
+ }
+ uint16_t sequenceParameterSetLength = stream->read_2bytes();
+ if (!stream->require(sequenceParameterSetLength)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data");
+ }
+ if (sequenceParameterSetLength > 0) {
+ vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength);
+ stream->read_bytes(&vcodec->sequenceParameterSetNALUnit[0], sequenceParameterSetLength);
+ }
+ }
+
+ // 1 pps
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS");
+ }
+ int8_t numOfPictureParameterSets = stream->read_1bytes();
+ numOfPictureParameterSets &= 0x1f;
+ if (numOfPictureParameterSets < 1) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
+ }
+ // Support for multiple PPS, then pick the first non-empty one.
+ for (int i = 0; i < numOfPictureParameterSets; ++i) {
+ if (!stream->require(2)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size");
+ }
+ uint16_t pictureParameterSetLength = stream->read_2bytes();
+ if (!stream->require(pictureParameterSetLength)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data");
+ }
+ if (pictureParameterSetLength > 0) {
+ vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength);
+ stream->read_bytes(&vcodec->pictureParameterSetNALUnit[0], pictureParameterSetLength);
+ }
+ }
+ return avc_demux_sps();
+}
+
+srs_error_t SrsFormat::avc_demux_sps()
+{
+ srs_error_t err = srs_success;
+
+ if (vcodec->sequenceParameterSetNALUnit.empty()) {
+ return err;
+ }
+
+ char *sps = &vcodec->sequenceParameterSetNALUnit[0];
+ int nbsps = (int)vcodec->sequenceParameterSetNALUnit.size();
+
+ SrsBuffer stream(sps, nbsps);
+
+ // for NALU, 7.3.1 NAL unit syntax
+ // ISO_IEC_14496-10-AVC-2012.pdf, page 61.
+ if (!stream.require(1)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS");
+ }
+ int8_t nutv = stream.read_1bytes();
+
+ // forbidden_zero_bit shall be equal to 0.
+ int8_t forbidden_zero_bit = (nutv >> 7) & 0x01;
+ if (forbidden_zero_bit) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "forbidden_zero_bit shall be equal to 0");
+ }
+
+ // nal_ref_idc not equal to 0 specifies that the content of the NAL unit contains a sequence parameter set or a picture
+ // parameter set or a slice of a reference picture or a slice data partition of a reference picture.
+ int8_t nal_ref_idc = (nutv >> 5) & 0x03;
+ if (!nal_ref_idc) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_ref_idc shall be not be equal to 0");
+ }
+
+ // 7.4.1 NAL unit semantics
+ // ISO_IEC_14496-10-AVC-2012.pdf, page 61.
+ // nal_unit_type specifies the type of RBSP data structure contained in the NAL unit as specified in Table 7-1.
+ SrsAvcNaluType nal_unit_type = SrsAvcNaluTypeParse(nutv);
+ if (nal_unit_type != 7) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "for sps, nal_unit_type shall be equal to 7");
+ }
+
+ // decode the rbsp from sps.
+ // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes.
+ std::vector rbsp(vcodec->sequenceParameterSetNALUnit.size());
+
+ int nb_rbsp = srs_rbsp_remove_emulation_bytes(&stream, rbsp);
+
+ return avc_demux_sps_rbsp((char *)&rbsp[0], nb_rbsp);
+}
+
+srs_error_t SrsFormat::avc_demux_sps_rbsp(char *rbsp, int nb_rbsp)
+{
+ srs_error_t err = srs_success;
+
+ // we donot parse the detail of sps.
+ // @see https://github.com/ossrs/srs/issues/474
+ if (!avc_parse_sps) {
+ return err;
+ }
+
+ // reparse the rbsp.
+ SrsBuffer stream(rbsp, nb_rbsp);
+
+ // for SPS, 7.3.2.1.1 Sequence parameter set data syntax
+ // ISO_IEC_14496-10-AVC-2012.pdf, page 62.
+ if (!stream.require(3)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps shall atleast 3bytes");
+ }
+ uint8_t profile_idc = stream.read_1bytes();
+ if (!profile_idc) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the profile_idc invalid");
+ }
+
+ int8_t flags = stream.read_1bytes();
+ if (flags & 0x03) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the flags invalid");
+ }
+
+ uint8_t level_idc = stream.read_1bytes();
+ if (!level_idc) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the level_idc invalid");
+ }
+
+ SrsBitBuffer bs(&stream);
+
+ int32_t seq_parameter_set_id = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, seq_parameter_set_id)) != srs_success) {
+ return srs_error_wrap(err, "read seq_parameter_set_id");
+ }
+ if (seq_parameter_set_id < 0) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the seq_parameter_set_id invalid");
+ }
+
+ int32_t chroma_format_idc = -1;
+ if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || profile_idc == 128) {
+ if ((err = srs_avc_nalu_read_uev(&bs, chroma_format_idc)) != srs_success) {
+ return srs_error_wrap(err, "read chroma_format_idc");
+ }
+ if (chroma_format_idc == 3) {
+ int8_t separate_colour_plane_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, separate_colour_plane_flag)) != srs_success) {
+ return srs_error_wrap(err, "read separate_colour_plane_flag");
+ }
+ }
+
+ int32_t bit_depth_luma_minus8 = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, bit_depth_luma_minus8)) != srs_success) {
+ return srs_error_wrap(err, "read bit_depth_luma_minus8");
+ ;
+ }
+
+ int32_t bit_depth_chroma_minus8 = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, bit_depth_chroma_minus8)) != srs_success) {
+ return srs_error_wrap(err, "read bit_depth_chroma_minus8");
+ ;
+ }
+
+ int8_t qpprime_y_zero_transform_bypass_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, qpprime_y_zero_transform_bypass_flag)) != srs_success) {
+ return srs_error_wrap(err, "read qpprime_y_zero_transform_bypass_flag");
+ ;
+ }
+
+ int8_t seq_scaling_matrix_present_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag)) != srs_success) {
+ return srs_error_wrap(err, "read seq_scaling_matrix_present_flag");
+ ;
+ }
+ if (seq_scaling_matrix_present_flag) {
+ int nb_scmpfs = ((chroma_format_idc != 3) ? 8 : 12);
+ for (int i = 0; i < nb_scmpfs; i++) {
+ int8_t seq_scaling_matrix_present_flag_i = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, seq_scaling_matrix_present_flag_i)) != srs_success) {
+ return srs_error_wrap(err, "read seq_scaling_matrix_present_flag_i");
+ ;
+ }
+ }
+ }
+ }
+
+ int32_t log2_max_frame_num_minus4 = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, log2_max_frame_num_minus4)) != srs_success) {
+ return srs_error_wrap(err, "read log2_max_frame_num_minus4");
+ ;
+ }
+
+ int32_t pic_order_cnt_type = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, pic_order_cnt_type)) != srs_success) {
+ return srs_error_wrap(err, "read pic_order_cnt_type");
+ ;
+ }
+
+ if (pic_order_cnt_type == 0) {
+ int32_t log2_max_pic_order_cnt_lsb_minus4 = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, log2_max_pic_order_cnt_lsb_minus4)) != srs_success) {
+ return srs_error_wrap(err, "read log2_max_pic_order_cnt_lsb_minus4");
+ ;
+ }
+ } else if (pic_order_cnt_type == 1) {
+ int8_t delta_pic_order_always_zero_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, delta_pic_order_always_zero_flag)) != srs_success) {
+ return srs_error_wrap(err, "read delta_pic_order_always_zero_flag");
+ ;
+ }
+
+ int32_t offset_for_non_ref_pic = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, offset_for_non_ref_pic)) != srs_success) {
+ return srs_error_wrap(err, "read offset_for_non_ref_pic");
+ ;
+ }
+
+ int32_t offset_for_top_to_bottom_field = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, offset_for_top_to_bottom_field)) != srs_success) {
+ return srs_error_wrap(err, "read offset_for_top_to_bottom_field");
+ ;
+ }
+
+ int32_t num_ref_frames_in_pic_order_cnt_cycle = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, num_ref_frames_in_pic_order_cnt_cycle)) != srs_success) {
+ return srs_error_wrap(err, "read num_ref_frames_in_pic_order_cnt_cycle");
+ ;
+ }
+ if (num_ref_frames_in_pic_order_cnt_cycle < 0) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "sps the num_ref_frames_in_pic_order_cnt_cycle");
+ }
+ for (int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
+ int32_t offset_for_ref_frame_i = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, offset_for_ref_frame_i)) != srs_success) {
+ return srs_error_wrap(err, "read offset_for_ref_frame_i");
+ ;
+ }
+ }
+ }
+
+ int32_t max_num_ref_frames = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, max_num_ref_frames)) != srs_success) {
+ return srs_error_wrap(err, "read max_num_ref_frames");
+ ;
+ }
+
+ int8_t gaps_in_frame_num_value_allowed_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, gaps_in_frame_num_value_allowed_flag)) != srs_success) {
+ return srs_error_wrap(err, "read gaps_in_frame_num_value_allowed_flag");
+ ;
+ }
+
+ int32_t pic_width_in_mbs_minus1 = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, pic_width_in_mbs_minus1)) != srs_success) {
+ return srs_error_wrap(err, "read pic_width_in_mbs_minus1");
+ ;
+ }
+
+ int32_t pic_height_in_map_units_minus1 = -1;
+ if ((err = srs_avc_nalu_read_uev(&bs, pic_height_in_map_units_minus1)) != srs_success) {
+ return srs_error_wrap(err, "read pic_height_in_map_units_minus1");
+ ;
+ }
+
+ int8_t frame_mbs_only_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, frame_mbs_only_flag)) != srs_success) {
+ return srs_error_wrap(err, "read frame_mbs_only_flag");
+ ;
+ }
+ if (!frame_mbs_only_flag) {
+ /* Skip mb_adaptive_frame_field_flag */
+ int8_t mb_adaptive_frame_field_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, mb_adaptive_frame_field_flag)) != srs_success) {
+ return srs_error_wrap(err, "read mb_adaptive_frame_field_flag");
+ ;
+ }
+ }
+
+ /* Skip direct_8x8_inference_flag */
+ int8_t direct_8x8_inference_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, direct_8x8_inference_flag)) != srs_success) {
+ return srs_error_wrap(err, "read direct_8x8_inference_flag");
+ ;
+ }
+
+ /* We need the following value to evaluate offsets, if any */
+ int8_t frame_cropping_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, frame_cropping_flag)) != srs_success) {
+ return srs_error_wrap(err, "read frame_cropping_flag");
+ ;
+ }
+ int32_t frame_crop_left_offset = 0, frame_crop_right_offset = 0,
+ frame_crop_top_offset = 0, frame_crop_bottom_offset = 0;
+ if (frame_cropping_flag) {
+ if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_left_offset)) != srs_success) {
+ return srs_error_wrap(err, "read frame_crop_left_offset");
+ ;
+ }
+ if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_right_offset)) != srs_success) {
+ return srs_error_wrap(err, "read frame_crop_right_offset");
+ ;
+ }
+ if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_top_offset)) != srs_success) {
+ return srs_error_wrap(err, "read frame_crop_top_offset");
+ ;
+ }
+ if ((err = srs_avc_nalu_read_uev(&bs, frame_crop_bottom_offset)) != srs_success) {
+ return srs_error_wrap(err, "read frame_crop_bottom_offset");
+ ;
+ }
+ }
+
+ /* Skip vui_parameters_present_flag */
+ int8_t vui_parameters_present_flag = -1;
+ if ((err = srs_avc_nalu_read_bit(&bs, vui_parameters_present_flag)) != srs_success) {
+ return srs_error_wrap(err, "read vui_parameters_present_flag");
+ ;
+ }
+
+ vcodec->width = ((pic_width_in_mbs_minus1 + 1) * 16) - frame_crop_left_offset * 2 - frame_crop_right_offset * 2;
+ vcodec->height = ((2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);
+
+ return err;
+}
+
+// LCOV_EXCL_STOP
+
+srs_error_t SrsFormat::video_nalu_demux(SrsBuffer *stream)
+{
+ srs_error_t err = srs_success;
+
+ // ensure the sequence header demuxed
+ if (!vcodec->is_avc_codec_ok()) {
+ srs_warn("avc ignore type=%d for no sequence header", SrsVideoAvcFrameTraitNALU);
+ return err;
+ }
+
+ if (vcodec->id == SrsVideoCodecIdHEVC) {
+ // TODO: FIXME: Might need to guess format?
+ return do_avc_demux_ibmf_format(stream);
+ }
+
+ // Parse the SPS/PPS in ANNEXB or IBMF format.
+ if (vcodec->payload_format == SrsAvcPayloadFormatIbmf) {
+ if ((err = avc_demux_ibmf_format(stream)) != srs_success) {
+ return srs_error_wrap(err, "avc demux ibmf");
+ }
+ } else if (vcodec->payload_format == SrsAvcPayloadFormatAnnexb) {
+ if ((err = avc_demux_annexb_format(stream)) != srs_success) {
+ return srs_error_wrap(err, "avc demux annexb");
+ }
+ } else {
+ if ((err = try_annexb_first ? avc_demux_annexb_format(stream) : avc_demux_ibmf_format(stream)) == srs_success) {
+ vcodec->payload_format = try_annexb_first ? SrsAvcPayloadFormatAnnexb : SrsAvcPayloadFormatIbmf;
+ } else {
+ srs_freep(err);
+ if ((err = try_annexb_first ? avc_demux_ibmf_format(stream) : avc_demux_annexb_format(stream)) == srs_success) {
+ vcodec->payload_format = try_annexb_first ? SrsAvcPayloadFormatIbmf : SrsAvcPayloadFormatAnnexb;
+ } else {
+ return srs_error_wrap(err, "avc demux try_annexb_first=%d", try_annexb_first);
+ }
+ }
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::avc_demux_annexb_format(SrsBuffer *stream)
+{
+ srs_error_t err = srs_success;
+
+ int pos = stream->pos();
+ err = do_avc_demux_annexb_format(stream);
+
+ // Restore the stream if error.
+ if (err != srs_success) {
+ stream->skip(pos - stream->pos());
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::do_avc_demux_annexb_format(SrsBuffer *stream)
+{
+ srs_error_t err = srs_success;
+
+ // not annexb, try others
+ if (!srs_avc_startswith_annexb(stream, NULL)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "not annexb");
+ }
+
+ // AnnexB
+ // B.1.1 Byte stream NAL unit syntax,
+ // ISO_IEC_14496-10-AVC-2003.pdf, page 211.
+ while (!stream->empty()) {
+ // find start code
+ int nb_start_code = 0;
+ if (!srs_avc_startswith_annexb(stream, &nb_start_code)) {
+ return err;
+ }
+
+ // skip the start code.
+ if (nb_start_code > 0) {
+ stream->skip(nb_start_code);
+ }
+
+ // the NALU start bytes.
+ char *p = stream->data() + stream->pos();
+
+ // get the last matched NALU
+ while (!stream->empty()) {
+ if (srs_avc_startswith_annexb(stream, NULL)) {
+ break;
+ }
+
+ stream->skip(1);
+ }
+
+ char *pp = stream->data() + stream->pos();
+
+ // skip the empty.
+ if (pp - p <= 0) {
+ continue;
+ }
+
+ // got the NALU.
+ if ((err = video->add_sample(p, (int)(pp - p))) != srs_success) {
+ return srs_error_wrap(err, "add video frame");
+ }
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::avc_demux_ibmf_format(SrsBuffer *stream)
+{
+ srs_error_t err = srs_success;
+
+ int pos = stream->pos();
+ err = do_avc_demux_ibmf_format(stream);
+
+ // Restore the stream if error.
+ if (err != srs_success) {
+ stream->skip(pos - stream->pos());
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::do_avc_demux_ibmf_format(SrsBuffer *stream)
+{
+ srs_error_t err = srs_success;
+
+ int PictureLength = stream->size() - stream->pos();
+
+ // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
+ // 5.2.4.1 AVC decoder configuration record
+ // 5.2.4.1.2 Semantics
+ // The value of this field shall be one of 0, 1, or 3 corresponding to a
+ // length encoded with 1, 2, or 4 bytes, respectively.
+ srs_assert(vcodec->NAL_unit_length != 2);
+
+ // 5.3.4.2.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
+ for (int i = 0; i < PictureLength;) {
+ // unsigned int((NAL_unit_length+1)*8) NALUnitLength;
+ // TODO: FIXME: Should ignore error? See https://github.com/ossrs/srs-gb28181/commit/a13b9b54938a14796abb9011e7a8ee779439a452
+ if (!stream->require(vcodec->NAL_unit_length + 1)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "PictureLength:%d, i:%d, NaluLength:%d, left:%d",
+ PictureLength, i, vcodec->NAL_unit_length, stream->left());
+ }
+ int32_t NALUnitLength = 0;
+ if (vcodec->NAL_unit_length == 3) {
+ NALUnitLength = stream->read_4bytes();
+ } else if (vcodec->NAL_unit_length == 1) {
+ NALUnitLength = stream->read_2bytes();
+ } else {
+ NALUnitLength = stream->read_1bytes();
+ }
+
+ // The stream format mighe be incorrect, see: https://github.com/ossrs/srs/issues/183
+ if (NALUnitLength < 0) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "PictureLength:%d, i:%d, NaluLength:%d, left:%d, NALUnitLength:%d",
+ PictureLength, i, vcodec->NAL_unit_length, stream->left(), NALUnitLength);
+ }
+
+ // NALUnit
+ if (!stream->require(NALUnitLength)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "PictureLength:%d, i:%d, NaluLength:%d, left:%d, NALUnitLength:%d",
+ PictureLength, i, vcodec->NAL_unit_length, stream->left(), NALUnitLength);
+ }
+ // 7.3.1 NAL unit syntax, ISO_IEC_14496-10-AVC-2003.pdf, page 44.
+ if ((err = video->add_sample(stream->data() + stream->pos(), NALUnitLength)) != srs_success) {
+ return srs_error_wrap(err, "avc add video frame");
+ }
+
+ stream->skip(NALUnitLength);
+ i += vcodec->NAL_unit_length + 1 + NALUnitLength;
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::audio_aac_demux(SrsBuffer *stream, int64_t timestamp)
+{
+ srs_error_t err = srs_success;
+
+ audio->cts = 0;
+ audio->dts = timestamp;
+
+ // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
+ int8_t sound_format = stream->read_1bytes();
+
+ int8_t sound_type = sound_format & 0x01;
+ int8_t sound_size = (sound_format >> 1) & 0x01;
+ int8_t sound_rate = (sound_format >> 2) & 0x03;
+ sound_format = (sound_format >> 4) & 0x0f;
+
+ SrsAudioCodecId codec_id = (SrsAudioCodecId)sound_format;
+ acodec->id = codec_id;
+
+ acodec->sound_type = (SrsAudioChannels)sound_type;
+ acodec->sound_rate = (SrsAudioSampleRate)sound_rate;
+ acodec->sound_size = (SrsAudioSampleBits)sound_size;
+
+ // we support h.264+mp3 for hls.
+ if (codec_id == SrsAudioCodecIdMP3) {
+ return srs_error_new(ERROR_HLS_TRY_MP3, "try mp3");
+ }
+
+ // only support aac
+ if (codec_id != SrsAudioCodecIdAAC) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "not supported codec %d", codec_id);
+ }
+
+ if (!stream->require(1)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode aac_packet_type");
+ }
+
+ SrsAudioAacFrameTrait aac_packet_type = (SrsAudioAacFrameTrait)stream->read_1bytes();
+ audio->aac_packet_type = (SrsAudioAacFrameTrait)aac_packet_type;
+
+ // Update the RAW AAC data.
+ raw = stream->data() + stream->pos();
+ nb_raw = stream->size() - stream->pos();
+
+ if (aac_packet_type == SrsAudioAacFrameTraitSequenceHeader) {
+ // AudioSpecificConfig
+ // 1.6.2.1 AudioSpecificConfig, in ISO_IEC_14496-3-AAC-2001.pdf, page 33.
+ int aac_extra_size = stream->size() - stream->pos();
+ if (aac_extra_size > 0) {
+ char *copy_stream_from = stream->data() + stream->pos();
+ acodec->aac_extra_data = std::vector(copy_stream_from, copy_stream_from + aac_extra_size);
+
+ if ((err = audio_aac_sequence_header_demux(&acodec->aac_extra_data[0], aac_extra_size)) != srs_success) {
+ return srs_error_wrap(err, "demux aac sh");
+ }
+ }
+ } else if (aac_packet_type == SrsAudioAacFrameTraitRawData) {
+ // ensure the sequence header demuxed
+ if (!acodec->is_aac_codec_ok()) {
+ srs_warn("aac ignore type=%d for no sequence header", aac_packet_type);
+ return err;
+ }
+
+ // Raw AAC frame data in UI8 []
+ // 6.3 Raw Data, ISO_IEC_13818-7-AAC-2004.pdf, page 28
+ if ((err = audio->add_sample(stream->data() + stream->pos(), stream->size() - stream->pos())) != srs_success) {
+ return srs_error_wrap(err, "add audio frame");
+ }
+ } else {
+ // ignored.
+ }
+
+ // reset the sample rate by sequence header
+ if (acodec->aac_sample_rate != SrsAacSampleRateUnset) {
+ static int srs_aac_srates[] = {
+ 96000, 88200, 64000, 48000,
+ 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000,
+ 7350, 0, 0, 0};
+ switch (srs_aac_srates[acodec->aac_sample_rate]) {
+ case 11025:
+ acodec->sound_rate = SrsAudioSampleRate11025;
+ break;
+ case 22050:
+ acodec->sound_rate = SrsAudioSampleRate22050;
+ break;
+ case 44100:
+ acodec->sound_rate = SrsAudioSampleRate44100;
+ break;
+ default:
+ break;
+ };
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::audio_mp3_demux(SrsBuffer *stream, int64_t timestamp, bool fresh)
+{
+ srs_error_t err = srs_success;
+
+ audio->cts = 0;
+ audio->dts = timestamp;
+ audio->aac_packet_type = fresh ? SrsAudioMp3FrameTraitSequenceHeader : SrsAudioMp3FrameTraitRawData;
+
+ // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
+ int8_t sound_format = stream->read_1bytes();
+
+ int8_t sound_type = sound_format & 0x01;
+ int8_t sound_size = (sound_format >> 1) & 0x01;
+ int8_t sound_rate = (sound_format >> 2) & 0x03;
+ sound_format = (sound_format >> 4) & 0x0f;
+
+ SrsAudioCodecId codec_id = (SrsAudioCodecId)sound_format;
+ acodec->id = codec_id;
+
+ acodec->sound_type = (SrsAudioChannels)sound_type;
+ acodec->sound_rate = (SrsAudioSampleRate)sound_rate;
+ acodec->sound_size = (SrsAudioSampleBits)sound_size;
+
+ // we always decode aac then mp3.
+ srs_assert(acodec->id == SrsAudioCodecIdMP3);
+
+ // Update the RAW MP3 data. Note the start is 12 bits syncword 0xFFF, so we should not skip any bytes, for detail
+ // please see ISO_IEC_11172-3-MP3-1993.pdf page 20 and 26.
+ raw = stream->data() + stream->pos();
+ nb_raw = stream->size() - stream->pos();
+
+ // mp3 payload.
+ if ((err = audio->add_sample(raw, nb_raw)) != srs_success) {
+ return srs_error_wrap(err, "add audio frame");
+ }
+
+ return err;
+}
+
+srs_error_t SrsFormat::audio_aac_sequence_header_demux(char *data, int size)
+{
+ srs_error_t err = srs_success;
+
+ SrsUniquePtr buffer(new SrsBuffer(data, size));
+
+ // only need to decode the first 2bytes:
+ // audioObjectType, aac_profile, 5bits.
+ // samplingFrequencyIndex, aac_sample_rate, 4bits.
+ // channelConfiguration, aac_channels, 4bits
+ if (!buffer->require(2)) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "audio codec decode aac sh");
+ }
+ uint8_t profile_ObjectType = buffer->read_1bytes();
+ uint8_t samplingFrequencyIndex = buffer->read_1bytes();
+
+ acodec->aac_channels = (samplingFrequencyIndex >> 3) & 0x0f;
+ samplingFrequencyIndex = ((profile_ObjectType << 1) & 0x0e) | ((samplingFrequencyIndex >> 7) & 0x01);
+ profile_ObjectType = (profile_ObjectType >> 3) & 0x1f;
+
+ // set the aac sample rate.
+ acodec->aac_sample_rate = samplingFrequencyIndex;
+
+ // convert the object type in sequence header to aac profile of ADTS.
+ acodec->aac_object = (SrsAacObjectType)profile_ObjectType;
+ if (acodec->aac_object == SrsAacObjectTypeReserved) {
+ return srs_error_new(ERROR_HLS_DECODE_ERROR, "aac decode sh object %d", profile_ObjectType);
+ }
+
+ // TODO: FIXME: to support aac he/he-v2, see: ngx_rtmp_codec_parse_aac_header
+ // @see: https://github.com/winlinvip/nginx-rtmp-module/commit/3a5f9eea78fc8d11e8be922aea9ac349b9dcbfc2
+ //
+ // donot force to LC, @see: https://github.com/ossrs/srs/issues/81
+ // the source will print the sequence header info.
+ // if (aac_profile > 3) {
+ // Mark all extended profiles as LC
+ // to make Android as happy as possible.
+ // @see: ngx_rtmp_hls_parse_aac_header
+ // aac_profile = 1;
+ //}
+
+ return err;
+}
diff --git a/trunk/src/kernel/srs_kernel_packet.hpp b/trunk/src/kernel/srs_kernel_packet.hpp
new file mode 100644
index 000000000..31c572c11
--- /dev/null
+++ b/trunk/src/kernel/srs_kernel_packet.hpp
@@ -0,0 +1,260 @@
+//
+// Copyright (c) 2013-2025 The SRS Authors
+//
+// SPDX-License-Identifier: MIT
+//
+
+#ifndef SRS_KERNEL_PACKET_HPP
+#define SRS_KERNEL_PACKET_HPP
+
+#include
+
+#include
+
+/**
+ * A sample is the NAL unit of a parsed packet.
+ * It's a NALU for H.264, H.265.
+ * It's the whole AAC raw data for AAC.
+ * @remark Neither SPS/PPS or ASC is sample unit, it's codec sequence header.
+ */
+class SrsNaluSample
+{
+public:
+ // The size of unit.
+ int size;
+ // The ptr of unit, user must free it.
+ char *bytes;
+
+public:
+ SrsNaluSample();
+ SrsNaluSample(char *b, int s);
+ ~SrsNaluSample();
+
+public:
+ // Copy sample, share the bytes pointer.
+ SrsNaluSample *copy();
+};
+
+// A media packet containing raw, undecoded media data.
+// This represents a single media frame or packet with timing information
+// and payload data, but without codec-specific parsing or decoding.
+class SrsMediaPacket
+{
+public:
+ // Timestamp of the media packet. The timebase is defined by context.
+ int64_t timestamp;
+ // Type of the media packet (audio, video, or script).
+ SrsFrameType message_type;
+
+public:
+ // Stream identifier for the packet. It's optional, so only used for some
+ // protocols, for example, RTMP.
+ int32_t stream_id;
+
+public:
+ // Raw payload data of the media packet.
+ SrsSharedPtr payload_;
+
+public:
+ SrsMediaPacket();
+ virtual ~SrsMediaPacket();
+
+public:
+ // Backward compatibility accessors
+ char *payload() { return payload_.get() ? payload_->payload() : NULL; }
+ int size() { return payload_.get() ? payload_->size() : 0; }
+
+public:
+ // Create shared ptr message from RAW payload.
+ // @remark Note that the header is set to zero.
+ virtual void wrap(char *payload, int size);
+ // check prefer cid and stream id.
+ // @return whether stream id already set.
+ virtual bool check(int stream_id);
+
+public:
+ virtual bool is_av();
+ virtual bool is_audio();
+ virtual bool is_video();
+
+public:
+ // copy current shared ptr message, use ref-count.
+ // @remark, assert object is created.
+ virtual SrsMediaPacket *copy();
+};
+
+// A parsed packet, consists of a codec and a group of samples.
+class SrsParsedPacket
+{
+public:
+ // The DTS/PTS in milliseconds, which is TBN=1000.
+ int64_t dts;
+ // PTS = DTS + CTS.
+ int32_t cts;
+
+public:
+ // The codec info of frame.
+ SrsCodecConfig *codec;
+ // The actual parsed number of samples.
+ int nb_samples;
+ // The sampels cache.
+ SrsNaluSample samples[SrsMaxNbSamples];
+
+public:
+ SrsParsedPacket();
+ virtual ~SrsParsedPacket();
+
+public:
+ // Initialize the frame, to parse sampels.
+ virtual srs_error_t initialize(SrsCodecConfig *c);
+ // Add a sample to frame.
+ virtual srs_error_t add_sample(char *bytes, int size);
+};
+
+// A parsed audio packet, besides a frame, contains the audio frame info, such as frame type.
+class SrsParsedAudioPacket : public SrsParsedPacket
+{
+public:
+ SrsAudioAacFrameTrait aac_packet_type;
+
+public:
+ SrsParsedAudioPacket();
+ virtual ~SrsParsedAudioPacket();
+
+public:
+ virtual SrsAudioCodecConfig *acodec();
+};
+
+// A parsed video packet, besides a frame, contains the video frame info, such as frame type.
+class SrsParsedVideoPacket : public SrsParsedPacket
+{
+public:
+ // video specified
+ SrsVideoAvcFrameType frame_type;
+ SrsVideoAvcFrameTrait avc_packet_type;
+ // whether sample_units contains IDR frame.
+ bool has_idr;
+ // Whether exists AUD NALU.
+ bool has_aud;
+ // Whether exists SPS/PPS NALU.
+ bool has_sps_pps;
+ // The first nalu type.
+ SrsAvcNaluType first_nalu_type;
+
+public:
+ SrsParsedVideoPacket();
+ virtual ~SrsParsedVideoPacket();
+
+public:
+ // Initialize the frame, to parse sampels.
+ virtual srs_error_t initialize(SrsCodecConfig *c);
+ // Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data.
+ virtual srs_error_t add_sample(char *bytes, int size);
+
+public:
+ virtual SrsVideoCodecConfig *vcodec();
+
+public:
+ static srs_error_t parse_avc_nalu_type(const SrsNaluSample *sample, SrsAvcNaluType &avc_nalu_type);
+ static srs_error_t parse_avc_bframe(const SrsNaluSample *sample, bool &is_b_frame);
+ static srs_error_t parse_hevc_nalu_type(const SrsNaluSample *sample, SrsHevcNaluType &hevc_nalu_type);
+ static srs_error_t parse_hevc_bframe(const SrsNaluSample *sample, SrsFormat *format, bool &is_b_frame);
+};
+
+/**
+ * A codec format, including one or many stream, each stream identified by a frame.
+ * For example, a typical RTMP stream format, consits of a video and audio frame.
+ * Maybe some RTMP stream only has a audio stream, for instance, redio application.
+ */
+class SrsFormat
+{
+public:
+ SrsParsedAudioPacket *audio;
+ SrsAudioCodecConfig *acodec;
+ SrsParsedVideoPacket *video;
+ SrsVideoCodecConfig *vcodec;
+
+public:
+ char *raw;
+ int nb_raw;
+
+public:
+ // for sequence header, whether parse the h.264 sps.
+ // TODO: FIXME: Refine it.
+ bool avc_parse_sps;
+ // Whether try to parse in ANNEXB, then by IBMF.
+ bool try_annexb_first;
+
+public:
+ SrsFormat();
+ virtual ~SrsFormat();
+
+public:
+ // Initialize the format.
+ virtual srs_error_t initialize();
+ // When got a parsed audio packet.
+ // @param data The data in FLV format.
+ virtual srs_error_t on_audio(int64_t timestamp, char *data, int size);
+ // When got a parsed video packet.
+ // @param data The data in FLV format.
+ virtual srs_error_t on_video(int64_t timestamp, char *data, int size);
+ // When got a audio aac sequence header.
+ virtual srs_error_t on_aac_sequence_header(char *data, int size);
+
+public:
+ virtual bool is_aac_sequence_header();
+ virtual bool is_mp3_sequence_header();
+ // TODO: is avc|hevc|av1 sequence header
+ virtual bool is_avc_sequence_header();
+
+private:
+ // Demux the video packet in H.264 codec.
+ // The packet is muxed in FLV format, defined in flv specification.
+ // Demux the sps/pps from sequence header.
+ // Demux the samples from NALUs.
+ virtual srs_error_t video_avc_demux(SrsBuffer *stream, int64_t timestamp);
+
+private:
+ virtual srs_error_t hevc_demux_hvcc(SrsBuffer *stream);
+
+private:
+ virtual srs_error_t hevc_demux_vps_sps_pps(SrsHevcHvccNalu *nal);
+ virtual srs_error_t hevc_demux_vps_rbsp(char *rbsp, int nb_rbsp);
+ virtual srs_error_t hevc_demux_sps_rbsp(char *rbsp, int nb_rbsp);
+ virtual srs_error_t hevc_demux_pps_rbsp(char *rbsp, int nb_rbsp);
+ virtual srs_error_t hevc_demux_rbsp_ptl(SrsBitBuffer *bs, SrsHevcProfileTierLevel *ptl, int profile_present_flag, int max_sub_layers_minus1);
+
+public:
+ virtual srs_error_t hevc_demux_vps(SrsBuffer *stream);
+ virtual srs_error_t hevc_demux_sps(SrsBuffer *stream);
+ virtual srs_error_t hevc_demux_pps(SrsBuffer *stream);
+
+private:
+ // Parse the H.264 SPS/PPS.
+ virtual srs_error_t avc_demux_sps_pps(SrsBuffer *stream);
+ virtual srs_error_t avc_demux_sps();
+ virtual srs_error_t avc_demux_sps_rbsp(char *rbsp, int nb_rbsp);
+
+private:
+ // Parse the H.264 or H.265 NALUs.
+ virtual srs_error_t video_nalu_demux(SrsBuffer *stream);
+ // Demux the avc NALU in "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
+ virtual srs_error_t avc_demux_annexb_format(SrsBuffer *stream);
+ virtual srs_error_t do_avc_demux_annexb_format(SrsBuffer *stream);
+ // Demux the avc NALU in "ISO Base Media File Format" from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
+ virtual srs_error_t avc_demux_ibmf_format(SrsBuffer *stream);
+ virtual srs_error_t do_avc_demux_ibmf_format(SrsBuffer *stream);
+
+private:
+ // Demux the audio packet in AAC codec.
+ // Demux the asc from sequence header.
+ // Demux the sampels from RAW data.
+ virtual srs_error_t audio_aac_demux(SrsBuffer *stream, int64_t timestamp);
+ virtual srs_error_t audio_mp3_demux(SrsBuffer *stream, int64_t timestamp, bool fresh);
+
+public:
+ // Directly demux the sequence header, without RTMP packet header.
+ virtual srs_error_t audio_aac_sequence_header_demux(char *data, int size);
+};
+
+#endif
diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp
index 9150acf3f..32db27cd1 100644
--- a/trunk/src/kernel/srs_kernel_rtc_rtp.cpp
+++ b/trunk/src/kernel/srs_kernel_rtc_rtp.cpp
@@ -1006,7 +1006,7 @@ SrsRtpRawPayload::SrsRtpRawPayload()
{
payload = NULL;
nn_payload = 0;
- sample_ = new SrsSample();
+ sample_ = new SrsNaluSample();
++_srs_pps_objs_rraw->sugar;
}
@@ -1077,19 +1077,19 @@ SrsRtpRawNALUs::~SrsRtpRawNALUs()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
srs_freep(p);
}
}
-void SrsRtpRawNALUs::push_back(SrsSample *sample)
+void SrsRtpRawNALUs::push_back(SrsNaluSample *sample)
{
if (sample->size <= 0) {
return;
}
if (!nalus.empty()) {
- SrsSample *p = new SrsSample();
+ SrsNaluSample *p = new SrsNaluSample();
p->bytes = (char *)"\0\0\1";
p->size = 3;
nn_bytes += 3;
@@ -1107,7 +1107,7 @@ uint8_t SrsRtpRawNALUs::skip_bytes(int count)
return uint8_t(nalus[0]->bytes[0]);
}
-srs_error_t SrsRtpRawNALUs::read_samples(vector &samples, int packet_size)
+srs_error_t SrsRtpRawNALUs::read_samples(vector &samples, int packet_size)
{
if (cursor + packet_size < 0 || cursor + packet_size > nn_bytes) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "cursor=%d, max=%d, size=%d", cursor, nn_bytes, packet_size);
@@ -1119,7 +1119,7 @@ srs_error_t SrsRtpRawNALUs::read_samples(vector &samples, int packe
int nn_nalus = (int)nalus.size();
for (int i = 0; left > 0 && i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
// Ignore previous consumed samples.
if (pos && pos - p->size >= 0) {
@@ -1131,7 +1131,7 @@ srs_error_t SrsRtpRawNALUs::read_samples(vector &samples, int packe
int nn = srs_min(left, p->size - pos);
srs_assert(nn > 0);
- SrsSample *sample = new SrsSample();
+ SrsNaluSample *sample = new SrsNaluSample();
samples.push_back(sample);
sample->bytes = p->bytes + pos;
@@ -1150,7 +1150,7 @@ uint64_t SrsRtpRawNALUs::nb_bytes()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
size += p->size;
}
@@ -1161,7 +1161,7 @@ srs_error_t SrsRtpRawNALUs::encode(SrsBuffer *buf)
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!buf->require(p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size);
@@ -1179,7 +1179,7 @@ srs_error_t SrsRtpRawNALUs::decode(SrsBuffer *buf)
return srs_success;
}
- SrsSample *sample = new SrsSample();
+ SrsNaluSample *sample = new SrsNaluSample();
sample->bytes = buf->head();
sample->size = buf->left();
buf->skip(sample->size);
@@ -1198,7 +1198,7 @@ ISrsRtpPayloader *SrsRtpRawNALUs::copy()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
cp->nalus.push_back(p->copy());
}
@@ -1216,16 +1216,16 @@ SrsRtpSTAPPayload::~SrsRtpSTAPPayload()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
srs_freep(p);
}
}
-SrsSample *SrsRtpSTAPPayload::get_sps()
+SrsNaluSample *SrsRtpSTAPPayload::get_sps()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!p || !p->size) {
continue;
}
@@ -1239,11 +1239,11 @@ SrsSample *SrsRtpSTAPPayload::get_sps()
return NULL;
}
-SrsSample *SrsRtpSTAPPayload::get_pps()
+SrsNaluSample *SrsRtpSTAPPayload::get_pps()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!p || !p->size) {
continue;
}
@@ -1263,7 +1263,7 @@ uint64_t SrsRtpSTAPPayload::nb_bytes()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
size += 2 + p->size;
}
@@ -1285,7 +1285,7 @@ srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer *buf)
// NALUs.
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!buf->require(2 + p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size);
@@ -1328,7 +1328,7 @@ srs_error_t SrsRtpSTAPPayload::decode(SrsBuffer *buf)
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", size);
}
- SrsSample *sample = new SrsSample();
+ SrsNaluSample *sample = new SrsNaluSample();
sample->bytes = buf->head();
sample->size = size;
buf->skip(size);
@@ -1347,7 +1347,7 @@ ISrsRtpPayloader *SrsRtpSTAPPayload::copy()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
cp->nalus.push_back(p->copy());
}
@@ -1366,7 +1366,7 @@ SrsRtpFUAPayload::~SrsRtpFUAPayload()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
srs_freep(p);
}
}
@@ -1377,7 +1377,7 @@ uint64_t SrsRtpFUAPayload::nb_bytes()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
size += p->size;
}
@@ -1408,7 +1408,7 @@ srs_error_t SrsRtpFUAPayload::encode(SrsBuffer *buf)
// FU payload, @see https://tools.ietf.org/html/rfc6184#section-5.8
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!buf->require(p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size);
@@ -1440,7 +1440,7 @@ srs_error_t SrsRtpFUAPayload::decode(SrsBuffer *buf)
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
}
- SrsSample *sample = new SrsSample();
+ SrsNaluSample *sample = new SrsNaluSample();
sample->bytes = buf->head();
sample->size = buf->left();
buf->skip(sample->size);
@@ -1461,7 +1461,7 @@ ISrsRtpPayloader *SrsRtpFUAPayload::copy()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
cp->nalus.push_back(p->copy());
}
@@ -1571,16 +1571,16 @@ SrsRtpSTAPPayloadHevc::~SrsRtpSTAPPayloadHevc()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
srs_freep(p);
}
}
-SrsSample *SrsRtpSTAPPayloadHevc::get_vps()
+SrsNaluSample *SrsRtpSTAPPayloadHevc::get_vps()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!p || !p->size) {
continue;
}
@@ -1594,11 +1594,11 @@ SrsSample *SrsRtpSTAPPayloadHevc::get_vps()
return NULL;
}
-SrsSample *SrsRtpSTAPPayloadHevc::get_sps()
+SrsNaluSample *SrsRtpSTAPPayloadHevc::get_sps()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!p || !p->size) {
continue;
}
@@ -1612,11 +1612,11 @@ SrsSample *SrsRtpSTAPPayloadHevc::get_sps()
return NULL;
}
-SrsSample *SrsRtpSTAPPayloadHevc::get_pps()
+SrsNaluSample *SrsRtpSTAPPayloadHevc::get_pps()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!p || !p->size) {
continue;
}
@@ -1636,7 +1636,7 @@ uint64_t SrsRtpSTAPPayloadHevc::nb_bytes()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
size += 2 + p->size;
}
@@ -1657,7 +1657,7 @@ srs_error_t SrsRtpSTAPPayloadHevc::encode(SrsBuffer *buf)
// NALUs.
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!buf->require(2 + p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2 + p->size);
@@ -1699,7 +1699,7 @@ srs_error_t SrsRtpSTAPPayloadHevc::decode(SrsBuffer *buf)
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", size);
}
- SrsSample *sample = new SrsSample();
+ SrsNaluSample *sample = new SrsNaluSample();
sample->bytes = buf->head();
sample->size = size;
buf->skip(size);
@@ -1716,7 +1716,7 @@ ISrsRtpPayloader *SrsRtpSTAPPayloadHevc::copy()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
cp->nalus.push_back(p->copy());
}
@@ -1735,7 +1735,7 @@ SrsRtpFUAPayloadHevc::~SrsRtpFUAPayloadHevc()
{
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
srs_freep(p);
}
}
@@ -1746,7 +1746,7 @@ uint64_t SrsRtpFUAPayloadHevc::nb_bytes()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
size += p->size;
}
@@ -1770,7 +1770,7 @@ srs_error_t SrsRtpFUAPayloadHevc::encode(SrsBuffer *buf)
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
if (!buf->require(p->size)) {
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", p->size);
@@ -1799,7 +1799,7 @@ srs_error_t SrsRtpFUAPayloadHevc::decode(SrsBuffer *buf)
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
}
- SrsSample *sample = new SrsSample();
+ SrsNaluSample *sample = new SrsNaluSample();
sample->bytes = buf->head();
sample->size = buf->left();
buf->skip(sample->size);
@@ -1819,7 +1819,7 @@ ISrsRtpPayloader *SrsRtpFUAPayloadHevc::copy()
int nn_nalus = (int)nalus.size();
for (int i = 0; i < nn_nalus; i++) {
- SrsSample *p = nalus[i];
+ SrsNaluSample *p = nalus[i];
cp->nalus.push_back(p->copy());
}
diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp
index 3cb3175d7..241b6af97 100644
--- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp
+++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp
@@ -12,6 +12,7 @@
#include
#include
#include
+#include
#include
#include
@@ -411,7 +412,7 @@ public:
public:
// Use the whole RAW RTP payload as a sample.
- SrsSample *sample_;
+ SrsNaluSample *sample_;
public:
SrsRtpRawPayload();
@@ -429,7 +430,7 @@ class SrsRtpRawNALUs : public ISrsRtpPayloader
{
private:
// We will manage the samples, but the sample itself point to the shared memory.
- std::vector nalus;
+ std::vector nalus;
int nn_bytes;
int cursor;
@@ -438,12 +439,12 @@ public:
virtual ~SrsRtpRawNALUs();
public:
- void push_back(SrsSample *sample);
+ void push_back(SrsNaluSample *sample);
public:
uint8_t skip_bytes(int count);
// We will manage the returned samples, if user want to manage it, please copy it.
- srs_error_t read_samples(std::vector &samples, int packet_size);
+ srs_error_t read_samples(std::vector &samples, int packet_size);
// interface ISrsRtpPayloader
public:
virtual uint64_t nb_bytes();
@@ -460,15 +461,15 @@ public:
SrsAvcNaluType nri;
// The NALU samples, we will manage the samples.
// @remark We only refer to the memory, user must free its bytes.
- std::vector nalus;
+ std::vector nalus;
public:
SrsRtpSTAPPayload();
virtual ~SrsRtpSTAPPayload();
public:
- SrsSample *get_sps();
- SrsSample *get_pps();
+ SrsNaluSample *get_sps();
+ SrsNaluSample *get_pps();
// interface ISrsRtpPayloader
public:
virtual uint64_t nb_bytes();
@@ -490,7 +491,7 @@ public:
SrsAvcNaluType nalu_type;
// The NALU samples, we manage the samples.
// @remark We only refer to the memory, user must free its bytes.
- std::vector nalus;
+ std::vector nalus;
public:
SrsRtpFUAPayload();
@@ -534,16 +535,16 @@ class SrsRtpSTAPPayloadHevc : public ISrsRtpPayloader
public:
// The NALU samples, we will manage the samples.
// @remark We only refer to the memory, user must free its bytes.
- std::vector nalus;
+ std::vector nalus;
public:
SrsRtpSTAPPayloadHevc();
virtual ~SrsRtpSTAPPayloadHevc();
public:
- SrsSample *get_vps();
- SrsSample *get_sps();
- SrsSample *get_pps();
+ SrsNaluSample *get_vps();
+ SrsNaluSample *get_sps();
+ SrsNaluSample *get_pps();
// interface ISrsRtpPayloader
public:
virtual uint64_t nb_bytes();
@@ -563,7 +564,7 @@ public:
SrsHevcNaluType nalu_type;
// The NALU samples, we manage the samples.
// @remark We only refer to the memory, user must free its bytes.
- std::vector nalus;
+ std::vector nalus;
public:
SrsRtpFUAPayloadHevc();
diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp
index 41745b820..80995123d 100644
--- a/trunk/src/kernel/srs_kernel_ts.cpp
+++ b/trunk/src/kernel/srs_kernel_ts.cpp
@@ -2917,7 +2917,7 @@ SrsTsMessageCache::~SrsTsMessageCache()
srs_freep(video);
}
-srs_error_t SrsTsMessageCache::cache_audio(SrsAudioFrame *frame, int64_t dts)
+srs_error_t SrsTsMessageCache::cache_audio(SrsParsedAudioPacket *frame, int64_t dts)
{
srs_error_t err = srs_success;
@@ -2951,7 +2951,7 @@ srs_error_t SrsTsMessageCache::cache_audio(SrsAudioFrame *frame, int64_t dts)
return err;
}
-srs_error_t SrsTsMessageCache::cache_video(SrsVideoFrame *frame, int64_t dts)
+srs_error_t SrsTsMessageCache::cache_video(SrsParsedVideoPacket *frame, int64_t dts)
{
srs_error_t err = srs_success;
@@ -2979,21 +2979,21 @@ srs_error_t SrsTsMessageCache::cache_video(SrsVideoFrame *frame, int64_t dts)
return err;
}
-srs_error_t SrsTsMessageCache::do_cache_mp3(SrsAudioFrame *frame)
+srs_error_t SrsTsMessageCache::do_cache_mp3(SrsParsedAudioPacket *frame)
{
srs_error_t err = srs_success;
// for mp3, directly write to cache.
// TODO: FIXME: implements the ts jitter.
for (int i = 0; i < frame->nb_samples; i++) {
- SrsSample *sample = &frame->samples[i];
+ SrsNaluSample *sample = &frame->samples[i];
audio->payload->append(sample->bytes, sample->size);
}
return err;
}
-srs_error_t SrsTsMessageCache::do_cache_aac(SrsAudioFrame *frame)
+srs_error_t SrsTsMessageCache::do_cache_aac(SrsParsedAudioPacket *frame)
{
srs_error_t err = srs_success;
@@ -3001,7 +3001,7 @@ srs_error_t SrsTsMessageCache::do_cache_aac(SrsAudioFrame *frame)
srs_assert(codec);
for (int i = 0; i < frame->nb_samples; i++) {
- SrsSample *sample = &frame->samples[i];
+ SrsNaluSample *sample = &frame->samples[i];
int32_t size = sample->size;
if (!sample->bytes || size <= 0 || size > 0x1fff) {
@@ -3118,7 +3118,7 @@ void srs_avc_insert_aud(SrsSimpleStream *payload, bool aud_inserted)
}
}
-srs_error_t SrsTsMessageCache::do_cache_avc(SrsVideoFrame *frame)
+srs_error_t SrsTsMessageCache::do_cache_avc(SrsParsedVideoPacket *frame)
{
srs_error_t err = srs_success;
@@ -3169,7 +3169,7 @@ srs_error_t SrsTsMessageCache::do_cache_avc(SrsVideoFrame *frame)
// all sample use cont nalu header, except the sps-pps before IDR frame.
for (int i = 0; i < frame->nb_samples; i++) {
- SrsSample *sample = &frame->samples[i];
+ SrsNaluSample *sample = &frame->samples[i];
int32_t size = sample->size;
if (!sample->bytes || size <= 0) {
@@ -3202,7 +3202,7 @@ srs_error_t SrsTsMessageCache::do_cache_avc(SrsVideoFrame *frame)
return err;
}
-srs_error_t SrsTsMessageCache::do_cache_hevc(SrsVideoFrame *frame)
+srs_error_t SrsTsMessageCache::do_cache_hevc(SrsParsedVideoPacket *frame)
{
srs_error_t err = srs_success;
@@ -3216,7 +3216,7 @@ srs_error_t SrsTsMessageCache::do_cache_hevc(SrsVideoFrame *frame)
// all sample use cont nalu header, except the sps-pps before IDR frame.
for (int i = 0; i < frame->nb_samples; i++) {
- SrsSample *sample = &frame->samples[i];
+ SrsNaluSample *sample = &frame->samples[i];
int32_t size = sample->size;
if (!sample->bytes || size <= 0) {
diff --git a/trunk/src/kernel/srs_kernel_ts.hpp b/trunk/src/kernel/srs_kernel_ts.hpp
index 29746cf52..28328b031 100644
--- a/trunk/src/kernel/srs_kernel_ts.hpp
+++ b/trunk/src/kernel/srs_kernel_ts.hpp
@@ -15,6 +15,7 @@
#include
#include
+#include
class SrsBuffer;
class SrsTsMessageCache;
@@ -1366,15 +1367,15 @@ public:
public:
// Write audio to cache
- virtual srs_error_t cache_audio(SrsAudioFrame *frame, int64_t dts);
+ virtual srs_error_t cache_audio(SrsParsedAudioPacket *frame, int64_t dts);
// Write video to muxer.
- virtual srs_error_t cache_video(SrsVideoFrame *frame, int64_t dts);
+ virtual srs_error_t cache_video(SrsParsedVideoPacket *frame, int64_t dts);
private:
- virtual srs_error_t do_cache_mp3(SrsAudioFrame *frame);
- virtual srs_error_t do_cache_aac(SrsAudioFrame *frame);
- virtual srs_error_t do_cache_avc(SrsVideoFrame *frame);
- virtual srs_error_t do_cache_hevc(SrsVideoFrame *frame);
+ virtual srs_error_t do_cache_mp3(SrsParsedAudioPacket *frame);
+ virtual srs_error_t do_cache_aac(SrsParsedAudioPacket *frame);
+ virtual srs_error_t do_cache_avc(SrsParsedVideoPacket *frame);
+ virtual srs_error_t do_cache_hevc(SrsParsedVideoPacket *frame);
};
// Transmux the RTMP stream to HTTP-TS stream.
diff --git a/trunk/src/protocol/srs_protocol_format.cpp b/trunk/src/protocol/srs_protocol_format.cpp
index 8b37f6b93..c9739fd8a 100644
--- a/trunk/src/protocol/srs_protocol_format.cpp
+++ b/trunk/src/protocol/srs_protocol_format.cpp
@@ -27,9 +27,9 @@ srs_error_t SrsRtmpFormat::on_metadata(SrsOnMetaDataPacket *meta)
return srs_success;
}
-srs_error_t SrsRtmpFormat::on_audio(SrsSharedPtrMessage *shared_audio)
+srs_error_t SrsRtmpFormat::on_audio(SrsMediaPacket *shared_audio)
{
- SrsSharedPtrMessage *msg = shared_audio;
+ SrsMediaPacket *msg = shared_audio;
char *data = msg->payload();
int size = msg->size();
@@ -41,9 +41,9 @@ srs_error_t SrsRtmpFormat::on_audio(int64_t timestamp, char *data, int size)
return SrsFormat::on_audio(timestamp, data, size);
}
-srs_error_t SrsRtmpFormat::on_video(SrsSharedPtrMessage *shared_video)
+srs_error_t SrsRtmpFormat::on_video(SrsMediaPacket *shared_video)
{
- SrsSharedPtrMessage *msg = shared_video;
+ SrsMediaPacket *msg = shared_video;
char *data = msg->payload();
int size = msg->size();
diff --git a/trunk/src/protocol/srs_protocol_format.hpp b/trunk/src/protocol/srs_protocol_format.hpp
index cc65b70a8..bc58f5321 100644
--- a/trunk/src/protocol/srs_protocol_format.hpp
+++ b/trunk/src/protocol/srs_protocol_format.hpp
@@ -10,9 +10,10 @@
#include
#include
+#include
class SrsOnMetaDataPacket;
-class SrsSharedPtrMessage;
+class SrsMediaPacket;
/**
* Create special structure from RTMP stream, for example, the metadata.
@@ -27,10 +28,10 @@ public:
// Initialize the format from metadata, optional.
virtual srs_error_t on_metadata(SrsOnMetaDataPacket *meta);
// When got a parsed audio packet.
- virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio);
+ virtual srs_error_t on_audio(SrsMediaPacket *shared_audio);
virtual srs_error_t on_audio(int64_t timestamp, char *data, int size);
// When got a parsed video packet.
- virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video);
+ virtual srs_error_t on_video(SrsMediaPacket *shared_video);
virtual srs_error_t on_video(int64_t timestamp, char *data, int size);
};
diff --git a/trunk/src/protocol/srs_protocol_raw_avc.cpp b/trunk/src/protocol/srs_protocol_raw_avc.cpp
index da2426a3e..f22ca09e7 100644
--- a/trunk/src/protocol/srs_protocol_raw_avc.cpp
+++ b/trunk/src/protocol/srs_protocol_raw_avc.cpp
@@ -14,6 +14,7 @@ using namespace std;
#include
#include