mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
add avc format doc. decode the flv codec info
This commit is contained in:
parent
b87318dec0
commit
ba234e8741
10 changed files with 387 additions and 97 deletions
BIN
trunk/doc/H.264-AVC-ISO_IEC_14496-15.pdf
Normal file
BIN
trunk/doc/H.264-AVC-ISO_IEC_14496-15.pdf
Normal file
Binary file not shown.
|
@ -151,6 +151,7 @@ int SrsClient::do_cycle()
|
|||
// find a source to publish.
|
||||
SrsSource* source = SrsSource::find(req->get_stream_url());
|
||||
srs_assert(source != NULL);
|
||||
SrsHLS* hls = source->get_hls();
|
||||
|
||||
bool enabled_cache = true;
|
||||
conf = config->get_gop_cache(req->vhost);
|
||||
|
@ -181,6 +182,7 @@ int SrsClient::do_cycle()
|
|||
}
|
||||
srs_info("start to publish stream %s success", req->stream.c_str());
|
||||
ret = publish(source, true);
|
||||
hls->on_unpublish();
|
||||
source->on_unpublish();
|
||||
return ret;
|
||||
}
|
||||
|
@ -193,6 +195,7 @@ int SrsClient::do_cycle()
|
|||
}
|
||||
srs_info("flash start to publish stream %s success", req->stream.c_str());
|
||||
ret = publish(source, false);
|
||||
hls->on_unpublish();
|
||||
source->on_unpublish();
|
||||
return ret;
|
||||
}
|
||||
|
@ -330,8 +333,15 @@ int SrsClient::publish(SrsSource* source, bool is_fmle)
|
|||
srs_verbose("check publish_refer success.");
|
||||
|
||||
SrsPithyPrint pithy_print(SRS_STAGE_PUBLISH_USER);
|
||||
|
||||
SrsHLS* hls = source->get_hls();
|
||||
|
||||
// notify the hls to prepare when publish start.
|
||||
if ((ret = hls->on_publish()) != ERROR_SUCCESS) {
|
||||
srs_error("hls on_publish failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("hls on_publish success.");
|
||||
|
||||
while (true) {
|
||||
// switch to other st-threads.
|
||||
st_usleep(0);
|
||||
|
@ -366,14 +376,26 @@ int SrsClient::process_publish_message(SrsSource* source, SrsHLS* hls, SrsCommon
|
|||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// process audio packet
|
||||
if (msg->header.is_audio() && ((ret = source->on_audio(msg)) != ERROR_SUCCESS)) {
|
||||
srs_error("process audio message failed. ret=%d", ret);
|
||||
return ret;
|
||||
if (msg->header.is_audio()) {
|
||||
if ((ret = hls->on_audio(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("hls process audio message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = source->on_audio(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("source process audio message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
// process video packet
|
||||
if (msg->header.is_video() && ((ret = source->on_video(msg)) != ERROR_SUCCESS)) {
|
||||
srs_error("process video message failed. ret=%d", ret);
|
||||
return ret;
|
||||
if (msg->header.is_video()) {
|
||||
if ((ret = hls->on_video(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("hls process video message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = source->on_video(msg)) != ERROR_SUCCESS) {
|
||||
srs_error("source process video message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// process onMetaData
|
||||
|
@ -386,8 +408,12 @@ int SrsClient::process_publish_message(SrsSource* source, SrsHLS* hls, SrsCommon
|
|||
SrsPacket* pkt = msg->get_packet();
|
||||
if (dynamic_cast<SrsOnMetaDataPacket*>(pkt)) {
|
||||
SrsOnMetaDataPacket* metadata = dynamic_cast<SrsOnMetaDataPacket*>(pkt);
|
||||
if ((ret = hls->on_meta_data(metadata)) != ERROR_SUCCESS) {
|
||||
srs_error("hls process onMetaData message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = source->on_meta_data(msg, metadata)) != ERROR_SUCCESS) {
|
||||
srs_error("process onMetaData message failed. ret=%d", ret);
|
||||
srs_error("source process onMetaData message failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_trace("process onMetaData message success.");
|
||||
|
|
|
@ -23,32 +23,84 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_core_codec.hpp>
|
||||
|
||||
#include <srs_core_error.hpp>
|
||||
#include <srs_core_stream.hpp>
|
||||
|
||||
SrsCodec::SrsCodec()
|
||||
{
|
||||
width = 0;
|
||||
height = 0;
|
||||
duration = 0;
|
||||
frame_rate = 0;
|
||||
video_data_rate = 0;
|
||||
video_codec_id = 0;
|
||||
audio_data_rate = 0;
|
||||
audio_codec_id = 0;
|
||||
aac_sample_rate = 0;
|
||||
sample_rate = 0;
|
||||
sample_size = 0;
|
||||
audio_channels = 0;
|
||||
profile = 0;
|
||||
level = 0;
|
||||
avc_extra_size = 0;
|
||||
avc_extra_data = NULL;
|
||||
aac_extra_size = 0;
|
||||
aac_extra_data = NULL;
|
||||
|
||||
stream = new SrsStream();
|
||||
}
|
||||
|
||||
SrsCodec::~SrsCodec()
|
||||
{
|
||||
srs_freepa(avc_extra_data);
|
||||
srs_freepa(aac_extra_data);
|
||||
|
||||
srs_freep(stream);
|
||||
}
|
||||
|
||||
int SrsCodec::parse_av_codec(bool is_video, int8_t* data, int size)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (!data || size <= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_video) {
|
||||
if (!stream->require(1)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t frame_type = stream->read_1bytes();
|
||||
int8_t codec_id = frame_type & 0x0f;
|
||||
frame_type = (frame_type >> 4) & 0x0f;
|
||||
|
||||
video_codec_id = codec_id;
|
||||
if (codec_id != SrsCodecVideoAVC) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!stream->require(4)) {
|
||||
return ret;
|
||||
}
|
||||
int8_t avc_packet_type = stream->read_1bytes();
|
||||
int32_t composition_time = stream->read_3bytes();
|
||||
|
||||
// 5.2.4.1.1 Syntax
|
||||
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
|
||||
{
|
||||
// E.4.3.1 VIDEODATA
|
||||
// Frame Type UB [4]
|
||||
// Type of video frame. The following values are defined:
|
||||
// 1 = key frame (for AVC, a seekable frame)
|
||||
// 2 = inter frame (for AVC, a non-seekable frame)
|
||||
// 3 = disposable inter frame (H.263 only)
|
||||
// 4 = generated key frame (reserved for server use only)
|
||||
// 5 = video info/command frame
|
||||
//
|
||||
// AVCPacketType IF CodecID == 7 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AVC sequence header
|
||||
// 1 = AVC NALU
|
||||
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
||||
// not required or supported)
|
||||
|
||||
// 2bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
|
@ -57,27 +109,11 @@ bool SrsCodec::video_is_keyframe(int8_t* data, int size)
|
|||
char frame_type = *(char*)data;
|
||||
frame_type = (frame_type >> 4) & 0x0F;
|
||||
|
||||
return frame_type == 1;
|
||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
||||
}
|
||||
|
||||
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
|
||||
{
|
||||
// E.4.3.1 VIDEODATA
|
||||
// Frame Type UB [4]
|
||||
// Type of video frame. The following values are defined:
|
||||
// 1 = key frame (for AVC, a seekable frame)
|
||||
// 2 = inter frame (for AVC, a non-seekable frame)
|
||||
// 3 = disposable inter frame (H.263 only)
|
||||
// 4 = generated key frame (reserved for server use only)
|
||||
// 5 = video info/command frame
|
||||
//
|
||||
// AVCPacketType IF CodecID == 7 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AVC sequence header
|
||||
// 1 = AVC NALU
|
||||
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
||||
// not required or supported)
|
||||
|
||||
// sequence header only for h264
|
||||
if (!video_is_h264(data, size)) {
|
||||
return false;
|
||||
|
@ -93,16 +129,12 @@ bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
|
|||
|
||||
char avc_packet_type = *(char*)(data + 1);
|
||||
|
||||
return frame_type == 1 && avc_packet_type == 0;
|
||||
return frame_type == SrsCodecVideoAVCFrameKeyFrame
|
||||
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
|
||||
}
|
||||
|
||||
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
|
||||
{
|
||||
// AACPacketType IF SoundFormat == 10 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AAC sequence header
|
||||
// 1 = AAC raw
|
||||
|
||||
// sequence header only for aac
|
||||
if (!audio_is_aac(data, size)) {
|
||||
return false;
|
||||
|
@ -115,21 +147,11 @@ bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
|
|||
|
||||
char aac_packet_type = *(char*)(data + 1);
|
||||
|
||||
return aac_packet_type == 0;
|
||||
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
|
||||
}
|
||||
|
||||
bool SrsCodec::video_is_h264(int8_t* data, int size)
|
||||
{
|
||||
// E.4.3.1 VIDEODATA
|
||||
// CodecID UB [4]
|
||||
// Codec Identifier. The following values are defined:
|
||||
// 2 = Sorenson H.263
|
||||
// 3 = Screen video
|
||||
// 4 = On2 VP6
|
||||
// 5 = On2 VP6 with alpha channel
|
||||
// 6 = Screen video version 2
|
||||
// 7 = AVC
|
||||
|
||||
// 1bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
|
@ -138,31 +160,11 @@ bool SrsCodec::video_is_h264(int8_t* data, int size)
|
|||
char codec_id = *(char*)data;
|
||||
codec_id = codec_id & 0x0F;
|
||||
|
||||
return codec_id == 7;
|
||||
return codec_id == SrsCodecVideoAVC;
|
||||
}
|
||||
|
||||
bool SrsCodec::audio_is_aac(int8_t* data, int size)
|
||||
{
|
||||
// SoundFormat UB [4]
|
||||
// Format of SoundData. The following values are defined:
|
||||
// 0 = Linear PCM, platform endian
|
||||
// 1 = ADPCM
|
||||
// 2 = MP3
|
||||
// 3 = Linear PCM, little endian
|
||||
// 4 = Nellymoser 16 kHz mono
|
||||
// 5 = Nellymoser 8 kHz mono
|
||||
// 6 = Nellymoser
|
||||
// 7 = G.711 A-law logarithmic PCM
|
||||
// 8 = G.711 mu-law logarithmic PCM
|
||||
// 9 = reserved
|
||||
// 10 = AAC
|
||||
// 11 = Speex
|
||||
// 14 = MP3 8 kHz
|
||||
// 15 = Device-specific sound
|
||||
// Formats 7, 8, 14, and 15 are reserved.
|
||||
// AAC is supported in Flash Player 9,0,115,0 and higher.
|
||||
// Speex is supported in Flash Player 10 and higher.
|
||||
|
||||
// 1bytes required.
|
||||
if (size < 1) {
|
||||
return false;
|
||||
|
@ -171,5 +173,5 @@ bool SrsCodec::audio_is_aac(int8_t* data, int size)
|
|||
char sound_format = *(char*)data;
|
||||
sound_format = (sound_format >> 4) & 0x0F;
|
||||
|
||||
return sound_format == 10;
|
||||
return sound_format == SrsCodecAudioAAC;
|
||||
}
|
||||
|
|
|
@ -30,36 +30,170 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
class SrsStream;
|
||||
|
||||
// E.4.3.1 VIDEODATA
|
||||
// CodecID UB [4]
|
||||
// Codec Identifier. The following values are defined:
|
||||
// 2 = Sorenson H.263
|
||||
// 3 = Screen video
|
||||
// 4 = On2 VP6
|
||||
// 5 = On2 VP6 with alpha channel
|
||||
// 6 = Screen video version 2
|
||||
// 7 = AVC
|
||||
enum SrsCodecVideo
|
||||
{
|
||||
SrsCodecVideoSorensonH263 = 2,
|
||||
SrsCodecVideoScreenVideo = 3,
|
||||
SrsCodecVideoOn2VP6 = 4,
|
||||
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
|
||||
SrsCodecVideoScreenVideoVersion2 = 6,
|
||||
SrsCodecVideoAVC = 7,
|
||||
};
|
||||
|
||||
// E.4.3.1 VIDEODATA
|
||||
// Frame Type UB [4]
|
||||
// Type of video frame. The following values are defined:
|
||||
// 1 = key frame (for AVC, a seekable frame)
|
||||
// 2 = inter frame (for AVC, a non-seekable frame)
|
||||
// 3 = disposable inter frame (H.263 only)
|
||||
// 4 = generated key frame (reserved for server use only)
|
||||
// 5 = video info/command frame
|
||||
enum SrsCodecVideoAVCFrame
|
||||
{
|
||||
SrsCodecVideoAVCFrameKeyFrame = 1,
|
||||
SrsCodecVideoAVCFrameInterFrame = 2,
|
||||
SrsCodecVideoAVCFrameDisposableInterFrame = 3,
|
||||
SrsCodecVideoAVCFrameGeneratedKeyFrame = 4,
|
||||
SrsCodecVideoAVCFrameVideoInfoFrame = 5,
|
||||
};
|
||||
|
||||
// AVCPacketType IF CodecID == 7 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AVC sequence header
|
||||
// 1 = AVC NALU
|
||||
// 2 = AVC end of sequence (lower level NALU sequence ender is
|
||||
// not required or supported)
|
||||
enum SrsCodecVideoAVCType
|
||||
{
|
||||
SrsCodecVideoAVCTypeSequenceHeader = 0,
|
||||
SrsCodecVideoAVCTypeNALU = 1,
|
||||
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
|
||||
};
|
||||
|
||||
// SoundFormat UB [4]
|
||||
// Format of SoundData. The following values are defined:
|
||||
// 0 = Linear PCM, platform endian
|
||||
// 1 = ADPCM
|
||||
// 2 = MP3
|
||||
// 3 = Linear PCM, little endian
|
||||
// 4 = Nellymoser 16 kHz mono
|
||||
// 5 = Nellymoser 8 kHz mono
|
||||
// 6 = Nellymoser
|
||||
// 7 = G.711 A-law logarithmic PCM
|
||||
// 8 = G.711 mu-law logarithmic PCM
|
||||
// 9 = reserved
|
||||
// 10 = AAC
|
||||
// 11 = Speex
|
||||
// 14 = MP3 8 kHz
|
||||
// 15 = Device-specific sound
|
||||
// Formats 7, 8, 14, and 15 are reserved.
|
||||
// AAC is supported in Flash Player 9,0,115,0 and higher.
|
||||
// Speex is supported in Flash Player 10 and higher.
|
||||
enum SrsCodecAudio
|
||||
{
|
||||
SrsCodecAudioLinearPCMPlatformEndian = 0,
|
||||
SrsCodecAudioADPCM = 1,
|
||||
SrsCodecAudioMP3 = 2,
|
||||
SrsCodecAudioLinearPCMLittleEndian = 3,
|
||||
SrsCodecAudioNellymoser16kHzMono = 4,
|
||||
SrsCodecAudioNellymoser8kHzMono = 5,
|
||||
SrsCodecAudioNellymoser = 6,
|
||||
SrsCodecAudioReservedG711AlawLogarithmicPCM = 7,
|
||||
SrsCodecAudioReservedG711MuLawLogarithmicPCM = 8,
|
||||
SrsCodecAudioReserved = 9,
|
||||
SrsCodecAudioAAC = 10,
|
||||
SrsCodecAudioSpeex = 11,
|
||||
SrsCodecAudioReservedMP3_8kHz = 14,
|
||||
SrsCodecAudioReservedDeviceSpecificSound = 15,
|
||||
};
|
||||
|
||||
// AACPacketType IF SoundFormat == 10 UI8
|
||||
// The following values are defined:
|
||||
// 0 = AAC sequence header
|
||||
// 1 = AAC raw
|
||||
enum SrsCodecAudioType
|
||||
{
|
||||
SrsCodecAudioTypeSequenceHeader = 0,
|
||||
SrsCodecAudioTypeRawData = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Annex E. The FLV File Format
|
||||
*/
|
||||
class SrsCodec
|
||||
{
|
||||
private:
|
||||
SrsStream* stream;
|
||||
public:
|
||||
/**
|
||||
* video specified
|
||||
*/
|
||||
int width;
|
||||
int height;
|
||||
int duration;
|
||||
int frame_rate;
|
||||
// @see: SrsCodecVideo
|
||||
int video_codec_id;
|
||||
int video_data_rate; // in bps
|
||||
u_int8_t profile; // profile_idc, page 45.
|
||||
u_int8_t level; // level_idc, page 45.
|
||||
/**
|
||||
* audio specified
|
||||
*/
|
||||
int audio_codec_id;
|
||||
int audio_data_rate; // in bps
|
||||
int aac_sample_rate;
|
||||
int sample_rate; /* 5512, 11025, 22050, 44100 */
|
||||
int sample_size; /* 1=8bit, 2=16bit */
|
||||
int audio_channels; /* 1, 2 */
|
||||
// the avc extra data, the AVC sequence header,
|
||||
// without the flv codec header
|
||||
int avc_extra_size;
|
||||
char* avc_extra_data;
|
||||
// the aac extra data, the AAC sequence header,
|
||||
// without the flv codec header
|
||||
int aac_extra_size;
|
||||
char* aac_extra_data;
|
||||
public:
|
||||
SrsCodec();
|
||||
virtual ~SrsCodec();
|
||||
// the following function used for hls to build the codec info.
|
||||
public:
|
||||
virtual int parse_av_codec(bool is_video, int8_t* data, int size);
|
||||
// the following function used to finger out the flv/rtmp packet detail.
|
||||
public:
|
||||
/**
|
||||
* only check the frame_type, not check the codec type.
|
||||
*/
|
||||
virtual bool video_is_keyframe(int8_t* data, int size);
|
||||
static bool video_is_keyframe(int8_t* data, int size);
|
||||
/**
|
||||
* check codec h264, keyframe, sequence header
|
||||
*/
|
||||
virtual bool video_is_sequence_header(int8_t* data, int size);
|
||||
static bool video_is_sequence_header(int8_t* data, int size);
|
||||
/**
|
||||
* check codec aac, sequence header
|
||||
*/
|
||||
virtual bool audio_is_sequence_header(int8_t* data, int size);
|
||||
static bool audio_is_sequence_header(int8_t* data, int size);
|
||||
/**
|
||||
* check codec h264.
|
||||
*/
|
||||
virtual bool video_is_h264(int8_t* data, int size);
|
||||
static bool video_is_h264(int8_t* data, int size);
|
||||
private:
|
||||
/**
|
||||
* check codec aac.
|
||||
*/
|
||||
virtual bool audio_is_aac(int8_t* data, int size);
|
||||
static bool audio_is_aac(int8_t* data, int size);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -23,11 +23,117 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_core_hls.hpp>
|
||||
|
||||
#include <srs_core_error.hpp>
|
||||
#include <srs_core_codec.hpp>
|
||||
#include <srs_core_amf0.hpp>
|
||||
#include <srs_core_protocol.hpp>
|
||||
|
||||
SrsHLS::SrsHLS()
|
||||
{
|
||||
codec = new SrsCodec();
|
||||
}
|
||||
|
||||
SrsHLS::~SrsHLS()
|
||||
{
|
||||
srs_freep(codec);
|
||||
}
|
||||
|
||||
int SrsHLS::on_publish()
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsHLS::on_unpublish()
|
||||
{
|
||||
}
|
||||
|
||||
int SrsHLS::on_meta_data(SrsOnMetaDataPacket* metadata)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (!metadata || !metadata->metadata) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsAmf0Object* obj = metadata->metadata;
|
||||
if (obj->size() <= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// finger out the codec info from metadata if possible.
|
||||
SrsAmf0Any* prop = NULL;
|
||||
|
||||
if ((prop = obj->get_property("duration")) != NULL && prop->is_number()) {
|
||||
codec->duration = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("width")) != NULL && prop->is_number()) {
|
||||
codec->width = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("height")) != NULL && prop->is_number()) {
|
||||
codec->height = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("framerate")) != NULL && prop->is_number()) {
|
||||
codec->frame_rate = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("videocodecid")) != NULL && prop->is_number()) {
|
||||
codec->video_codec_id = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("videodatarate")) != NULL && prop->is_number()) {
|
||||
codec->video_data_rate = (int)(1000 * srs_amf0_convert<SrsAmf0Number>(prop)->value);
|
||||
}
|
||||
|
||||
if ((prop = obj->get_property("audiocodecid")) != NULL && prop->is_number()) {
|
||||
codec->audio_codec_id = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("audiodatarate")) != NULL && prop->is_number()) {
|
||||
codec->audio_data_rate = (int)(1000 * srs_amf0_convert<SrsAmf0Number>(prop)->value);
|
||||
}
|
||||
if ((prop = obj->get_property("audiosamplerate")) != NULL && prop->is_number()) {
|
||||
codec->sample_rate = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
}
|
||||
if ((prop = obj->get_property("audiosamplesize")) != NULL && prop->is_number()) {
|
||||
codec->sample_size = (int)srs_amf0_convert<SrsAmf0Number>(prop)->value;
|
||||
if (codec->sample_size == 16) {
|
||||
codec->sample_size = 2;
|
||||
} else {
|
||||
codec->sample_size = 1;
|
||||
}
|
||||
}
|
||||
if ((prop = obj->get_property("stereo")) != NULL && prop->is_number()) {
|
||||
if (srs_amf0_convert<SrsAmf0Boolean>(prop)->value) {
|
||||
codec->audio_channels = 2;
|
||||
} else {
|
||||
codec->audio_channels = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsHLS::on_audio(SrsCommonMessage* audio)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = codec->parse_av_codec(false, audio->payload, audio->size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsHLS::on_video(SrsCommonMessage* video)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if ((ret = codec->parse_av_codec(true, video->payload, video->size)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (codec->video_codec_id != SrsCodecVideoAVC) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
*/
|
||||
#include <srs_core.hpp>
|
||||
|
||||
class SrsOnMetaDataPacket;
|
||||
class SrsCommonMessage;
|
||||
class SrsCodec;
|
||||
|
||||
class SrsHLS
|
||||
{
|
||||
private:
|
||||
SrsCodec* codec;
|
||||
public:
|
||||
SrsHLS();
|
||||
virtual ~SrsHLS();
|
||||
public:
|
||||
virtual int on_publish();
|
||||
virtual void on_unpublish();
|
||||
virtual int on_meta_data(SrsOnMetaDataPacket* metadata);
|
||||
virtual int on_audio(SrsCommonMessage* audio);
|
||||
virtual int on_video(SrsCommonMessage* video);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -53,13 +53,11 @@ SrsConsumer::SrsConsumer(SrsSource* _source)
|
|||
source = _source;
|
||||
last_pkt_correct_time = last_pkt_time = 0;
|
||||
paused = false;
|
||||
codec = new SrsCodec();
|
||||
}
|
||||
|
||||
SrsConsumer::~SrsConsumer()
|
||||
{
|
||||
clear();
|
||||
srs_freep(codec);
|
||||
clear();
|
||||
|
||||
source->on_consumer_destroy(this);
|
||||
}
|
||||
|
@ -141,7 +139,7 @@ void SrsConsumer::shrink()
|
|||
SrsSharedPtrMessage* msg = *it;
|
||||
if (msg->header.is_video()) {
|
||||
has_video = true;
|
||||
if (codec->video_is_keyframe(msg->payload, msg->size)) {
|
||||
if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) {
|
||||
iframe = it;
|
||||
frame_to_remove = i + 1;
|
||||
}
|
||||
|
@ -240,7 +238,6 @@ void SrsConsumer::clear()
|
|||
SrsSource::SrsSource(std::string _stream_url)
|
||||
{
|
||||
stream_url = _stream_url;
|
||||
codec = new SrsCodec();
|
||||
hls = new SrsHLS();
|
||||
|
||||
cache_metadata = cache_sh_video = cache_sh_audio = NULL;
|
||||
|
@ -266,7 +263,6 @@ SrsSource::~SrsSource()
|
|||
srs_freep(cache_sh_video);
|
||||
srs_freep(cache_sh_audio);
|
||||
|
||||
srs_freep(codec);
|
||||
srs_freep(hls);
|
||||
}
|
||||
|
||||
|
@ -364,7 +360,7 @@ int SrsSource::on_audio(SrsCommonMessage* audio)
|
|||
srs_info("dispatch audio success.");
|
||||
|
||||
// cache the sequence header if h264
|
||||
if (codec->audio_is_sequence_header(msg->payload, msg->size)) {
|
||||
if (SrsCodec::audio_is_sequence_header(msg->payload, msg->size)) {
|
||||
srs_freep(cache_sh_audio);
|
||||
cache_sh_audio = msg->copy();
|
||||
srs_trace("update audio sequence header success. size=%d", msg->header.payload_length);
|
||||
|
@ -409,7 +405,7 @@ int SrsSource::on_video(SrsCommonMessage* video)
|
|||
srs_info("dispatch video success.");
|
||||
|
||||
// cache the sequence header if h264
|
||||
if (codec->video_is_sequence_header(msg->payload, msg->size)) {
|
||||
if (SrsCodec::video_is_sequence_header(msg->payload, msg->size)) {
|
||||
srs_freep(cache_sh_video);
|
||||
cache_sh_video = msg->copy();
|
||||
srs_trace("update video sequence header success. size=%d", msg->header.payload_length);
|
||||
|
@ -521,7 +517,7 @@ int SrsSource::cache_last_gop(SrsSharedPtrMessage* msg)
|
|||
}
|
||||
|
||||
// clear gop cache when got key frame
|
||||
if (msg->header.is_video() && codec->video_is_keyframe(msg->payload, msg->size)) {
|
||||
if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) {
|
||||
srs_info("clear gop cache when got keyframe. vcount=%d, count=%d",
|
||||
cached_video_count, (int)gop_cache.size());
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class SrsCodec;
|
||||
class SrsSource;
|
||||
class SrsCommonMessage;
|
||||
class SrsOnMetaDataPacket;
|
||||
|
@ -52,7 +51,6 @@ private:
|
|||
SrsSource* source;
|
||||
std::vector<SrsSharedPtrMessage*> msgs;
|
||||
bool paused;
|
||||
SrsCodec* codec;
|
||||
public:
|
||||
SrsConsumer(SrsSource* _source);
|
||||
virtual ~SrsConsumer();
|
||||
|
@ -108,7 +106,6 @@ public:
|
|||
static SrsSource* find(std::string stream_url);
|
||||
private:
|
||||
SrsHLS* hls;
|
||||
SrsCodec* codec;
|
||||
std::string stream_url;
|
||||
std::vector<SrsConsumer*> consumers;
|
||||
// gop cache for client fast startup.
|
||||
|
|
|
@ -106,6 +106,19 @@ int16_t SrsStream::read_2bytes()
|
|||
return value;
|
||||
}
|
||||
|
||||
int32_t SrsStream::read_3bytes()
|
||||
{
|
||||
srs_assert(require(3));
|
||||
|
||||
int32_t value = 0x00;
|
||||
pp = (char*)&value;
|
||||
pp[2] = *p++;
|
||||
pp[1] = *p++;
|
||||
pp[0] = *p++;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int32_t SrsStream::read_4bytes()
|
||||
{
|
||||
srs_assert(require(4));
|
||||
|
|
|
@ -84,6 +84,10 @@ public:
|
|||
*/
|
||||
virtual int16_t read_2bytes();
|
||||
/**
|
||||
* get 3bytes int from stream.
|
||||
*/
|
||||
virtual int32_t read_3bytes();
|
||||
/**
|
||||
* get 4bytes int from stream.
|
||||
*/
|
||||
virtual int32_t read_4bytes();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue