1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

For #299, refine the codec to format-frame-sample chain.

This commit is contained in:
winlin 2017-02-12 18:18:18 +08:00
parent c4a510b834
commit d7458c4e72
18 changed files with 990 additions and 1150 deletions

View file

@ -93,7 +93,6 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size)
// @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
int8_t sound_format = stream->read_1bytes();
// @see: SrsAvcAacCodec::audio_aac_demux
//int8_t sound_type = sound_format & 0x01;
//int8_t sound_size = (sound_format >> 1) & 0x01;
//int8_t sound_rate = (sound_format >> 2) & 0x03;

File diff suppressed because it is too large Load diff

View file

@ -201,7 +201,6 @@ enum SrsCodecFlvTag
/**
* Annex E. The FLV File Format
* @see SrsAvcAacCodec for the media stream codec.
*/
class SrsFlvCodec
{
@ -375,6 +374,7 @@ std::string srs_codec_aac_profile2str(SrsAacProfile aac_profile);
enum SrsAacObjectType
{
SrsAacObjectTypeReserved = 0,
SrsAacObjectTypeForbidden = 0,
// Table 1.1 - Audio Object Type definition
// @see @see ISO_IEC_14496-3-AAC-2001.pdf, page 23
@ -454,9 +454,9 @@ class SrsSample
{
public:
// The size of unit.
int nb_unit;
int size;
// The ptr of unit, user must manage it.
char* unit;
char* bytes;
public:
SrsSample();
virtual ~SrsSample();
@ -472,9 +472,6 @@ class SrsCodec
public:
SrsCodec();
virtual ~SrsCodec();
public:
// Get the codec type.
virtual SrsCodecFlvTag codec() = 0;
};
/**
@ -484,17 +481,41 @@ class SrsAudioCodec : public SrsCodec
{
public:
// audio specified
SrsCodecAudio acodec;
SrsCodecAudio id;
// audio aac specified.
SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type;
int audio_data_rate; // in bps
public:
/**
* audio specified
* audioObjectType, in 1.6.2.1 AudioSpecificConfig, page 33,
* 1.5.1.1 Audio object type definition, page 23,
* in ISO_IEC_14496-3-AAC-2001.pdf.
*/
SrsAacObjectType aac_object;
/**
* samplingFrequencyIndex
*/
uint8_t aac_sample_rate;
/**
* channelConfiguration
*/
uint8_t aac_channels;
public:
/**
* the aac extra data, the AAC sequence header,
* without the flv codec header,
* @see: ffmpeg, AVCodecContext::extradata
*/
int aac_extra_size;
char* aac_extra_data;
public:
SrsAudioCodec();
virtual ~SrsAudioCodec();
public:
virtual SrsCodecFlvTag codec();
virtual bool is_aac_codec_ok();
};
/**
@ -503,29 +524,54 @@ public:
class SrsVideoCodec : public SrsCodec
{
public:
// video specified
SrsCodecVideoAVCFrame frame_type;
SrsCodecVideoAVCType 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;
SrsCodecVideo id;
int video_data_rate; // in bps
double frame_rate;
double duration;
int width;
int height;
public:
/**
* the avc extra data, the AVC sequence header,
* without the flv codec header,
* @see: ffmpeg, AVCodecContext::extradata
*/
int avc_extra_size;
char* avc_extra_data;
public:
/**
* video specified
*/
// profile_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
SrsAvcProfile avc_profile;
// level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
SrsAvcLevel avc_level;
// lengthSizeMinusOne, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
int8_t NAL_unit_length;
uint16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit;
uint16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit;
public:
// the avc payload format.
SrsAvcPayloadFormat payload_format;
public:
SrsVideoCodec();
virtual ~SrsVideoCodec();
public:
virtual SrsCodecFlvTag codec();
virtual bool is_avc_codec_ok();
};
/**
* A codec frame, consists of a codec and a group of samples.
* A frame, consists of a codec and a group of samples.
*/
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.
SrsCodec* codec;
@ -536,43 +582,32 @@ public:
public:
SrsFrame();
virtual ~SrsFrame();
public:
// Initialize the frame, to parse sampels.
virtual int initialize(SrsCodec* c);
// Add a sample to frame.
virtual int add_sample(char* bytes, int size);
};
/**
* the samples in the flv audio/video packet.
* the sample used to analysis a video/audio packet,
* split the h.264 NALUs to buffers, or aac raw data to a buffer,
* and decode the video/audio specified infos.
*
* the sample unit:
* a video packet codec in h.264 contains many NALUs, each is a sample unit.
* a audio packet codec in aac is a sample unit.
* @remark, the video/audio sequence header is not sample unit,
* all sequence header stores as extra data,
* @see SrsAvcAacCodec.avc_extra_data and SrsAvcAacCodec.aac_extra_data
* @remark, user must clear all samples before decode a new video/audio packet.
*/
class SrsCodecSample
* A audio frame, besides a frame, contains the audio frame info, such as frame type.
*/
class SrsAudioFrame : public SrsFrame
{
public:
/**
* each audio/video raw data packet will dumps to one or multiple buffers,
* the buffers will write to hls and clear to reset.
* generally, aac audio packet corresponding to one buffer,
* where avc/h264 video packet may contains multiple buffer.
*/
int nb_sample_units;
SrsCodecSampleUnit sample_units[SRS_MAX_CODEC_SAMPLE];
SrsCodecAudioType aac_packet_type;
public:
/**
* whether the sample is video sample which demux from video packet.
*/
bool is_video;
/**
* CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
* cts = pts - dts, where dts = flvheader->timestamp.
*/
int32_t cts;
SrsAudioFrame();
virtual ~SrsAudioFrame();
public:
virtual SrsAudioCodec* acodec();
};
/**
* A video frame, besides a frame, contains the video frame info, such as frame type.
*/
class SrsVideoFrame : public SrsFrame
{
public:
// video specified
SrsCodecVideoAVCFrame frame_type;
@ -586,171 +621,74 @@ public:
// The first nalu type.
SrsAvcNaluType first_nalu_type;
public:
// audio specified
SrsCodecAudio acodec;
// audio aac specified.
SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type;
SrsVideoFrame();
virtual ~SrsVideoFrame();
public:
SrsCodecSample();
virtual ~SrsCodecSample();
// Add the sample without ANNEXB or IBMF header, or RAW AAC or MP3 data.
virtual int add_sample(char* bytes, int size);
public:
/**
* clear all samples.
* the sample units never copy the bytes, it directly use the ptr,
* so when video/audio packet is destroyed, the sample must be clear.
* in a word, user must clear sample before demux it.
* @remark demux sample use SrsAvcAacCodec.audio_aac_demux or video_avc_demux.
*/
void clear();
/**
* add the a sample unit, it's a h.264 NALU or aac raw data.
* the sample unit directly use the ptr of packet bytes,
* so user must never use sample unit when packet is destroyed.
* in a word, user must clear sample before demux it.
*/
int add_sample_unit(char* bytes, int size);
virtual SrsVideoCodec* vcodec();
};
/**
* the h264/avc and aac codec, for media stream.
*
* to demux the FLV/RTMP video/audio packet to sample,
* add each NALUs of h.264 as a sample unit to sample,
* while the entire aac raw data as a sample unit.
*
* for sequence header,
* demux it and save it in the avc_extra_data and aac_extra_data,
*
* for the codec info, such as audio sample rate,
* decode from FLV/RTMP header, then use codec info in sequence
* header to override it.
*/
class SrsAvcAacCodec
* 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
{
private:
SrsBuffer* stream;
public:
/**
* metadata specified
*/
int duration;
int width;
int height;
int frame_rate;
// @see: SrsCodecVideo
int video_codec_id;
int video_data_rate; // in bps
// @see: SrsCod ecAudioType
int audio_codec_id;
int audio_data_rate; // in bps
public:
/**
* video specified
*/
// profile_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
SrsAvcProfile avc_profile;
// level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
SrsAvcLevel avc_level;
// lengthSizeMinusOne, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
int8_t NAL_unit_length;
uint16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit;
uint16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit;
private:
// the avc payload format.
SrsAvcPayloadFormat payload_format;
public:
/**
* audio specified
* audioObjectType, in 1.6.2.1 AudioSpecificConfig, page 33,
* 1.5.1.1 Audio object type definition, page 23,
* in ISO_IEC_14496-3-AAC-2001.pdf.
*/
SrsAacObjectType aac_object;
/**
* samplingFrequencyIndex
*/
uint8_t aac_sample_rate;
/**
* channelConfiguration
*/
uint8_t aac_channels;
public:
/**
* the avc extra data, the AVC sequence header,
* without the flv codec header,
* @see: ffmpeg, AVCodecContext::extradata
*/
int avc_extra_size;
char* avc_extra_data;
/**
* the aac extra data, the AAC sequence header,
* without the flv codec header,
* @see: ffmpeg, AVCodecContext::extradata
*/
int aac_extra_size;
char* aac_extra_data;
SrsAudioFrame* audio;
SrsAudioCodec* acodec;
SrsVideoFrame* video;
SrsVideoCodec* vcodec;
SrsBuffer* buffer;
public:
// for sequence header, whether parse the h.264 sps.
// TODO: FIXME: Refine it.
bool avc_parse_sps;
public:
SrsAvcAacCodec();
virtual ~SrsAvcAacCodec();
SrsFormat();
virtual ~SrsFormat();
public:
// whether avc or aac codec sequence header or extra data is decoded ok.
virtual bool is_avc_codec_ok();
virtual bool is_aac_codec_ok();
// the following function used for hls to build the sample and codec.
// Initialize the format.
virtual int initialize();
// When got a parsed audio packet.
virtual int on_audio(int64_t timestamp, char* data, int size);
// When got a parsed video packet.
virtual int on_video(int64_t timestamp, char* data, int size);
// When got a audio aac sequence header.
virtual int on_aac_sequence_header(char* data, int size);
public:
/**
* demux the audio packet in aac codec.
* the packet mux in FLV/RTMP format defined in flv specification.
* demux the audio speicified data(sound_format, sound_size, ...) to sample.
* demux the aac specified data(aac_profile, ...) to codec from sequence header.
* demux the aac raw to sample units.
*/
virtual int audio_aac_demux(char* data, int size, SrsCodecSample* sample);
virtual int audio_mp3_demux(char* data, int size, SrsCodecSample* sample);
/**
* demux the video packet in h.264 codec.
* the packet mux in FLV/RTMP format defined in flv specification.
* demux the video specified data(frame_type, codec_id, ...) to sample.
* demux the h.264 sepcified data(avc_profile, ...) to codec from sequence header.
* demux the h.264 NALUs to sampe units.
*/
virtual int video_avc_demux(char* data, int size, SrsCodecSample* sample);
virtual bool is_aac_sequence_header();
virtual bool is_avc_sequence_header();
private:
virtual int video_nalu_demux(SrsBuffer* stream, SrsCodecSample* sample);
public:
/**
* directly demux the sequence header, without RTMP packet header.
*/
virtual int audio_aac_sequence_header_demux(char* data, int size);
// 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 int video_avc_demux(SrsBuffer* stream, int64_t timestamp);
private:
/**
* when avc packet type is SrsCodecVideoAVCTypeSequenceHeader,
* decode the sps and pps.
*/
// Parse the H.264 SPS/PPS.
virtual int avc_demux_sps_pps(SrsBuffer* stream);
/**
* decode the sps rbsp stream.
*/
virtual int avc_demux_sps();
virtual int avc_demux_sps_rbsp(char* rbsp, int nb_rbsp);
/**
* demux the avc NALU in "AnnexB"
* from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
*/
virtual int avc_demux_annexb_format(SrsBuffer* stream, SrsCodecSample* sample);
/**
* demux the avc NALU in "ISO Base Media File Format"
* from ISO_IEC_14496-15-AVC-format-2012.pdf, page 20
*/
virtual int avc_demux_ibmf_format(SrsBuffer* stream, SrsCodecSample* sample);
private:
// Parse the H.264 NALUs.
virtual int video_nalu_demux(SrsBuffer* stream);
// Demux the avc NALU in "AnnexB" from ISO_IEC_14496-10-AVC-2003.pdf, page 211.
virtual int 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 int 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 int audio_aac_demux(SrsBuffer* stream, int64_t timestamp);
virtual int audio_mp3_demux(SrsBuffer* stream, int64_t timestamp);
public:
// Directly demux the sequence header, without RTMP packet header.
virtual int audio_aac_sequence_header_demux(char* data, int size);
};
#endif

View file

@ -106,7 +106,6 @@ int SrsMp3Encoder::write_audio(int64_t timestamp, char* data, int size)
// @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
int8_t sound_format = stream->read_1bytes();
// @see: SrsAvcAacCodec::audio_aac_demux
//int8_t sound_type = sound_format & 0x01;
//int8_t sound_size = (sound_format >> 1) & 0x01;
//int8_t sound_rate = (sound_format >> 2) & 0x03;

View file

@ -2708,7 +2708,7 @@ int SrsTsPayloadPMT::psi_encode(SrsBuffer* stream)
return ret;
}
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc)
SrsTsMuxer::SrsTsMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc)
{
writer = w;
context = c;
@ -2717,12 +2717,12 @@ SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsC
vcodec = vc;
}
SrsTSMuxer::~SrsTSMuxer()
SrsTsMuxer::~SrsTsMuxer()
{
close();
}
int SrsTSMuxer::open(string p)
int SrsTsMuxer::open(string p)
{
int ret = ERROR_SUCCESS;
@ -2740,13 +2740,13 @@ int SrsTSMuxer::open(string p)
return ret;
}
int SrsTSMuxer::update_acodec(SrsCodecAudio ac)
int SrsTsMuxer::update_acodec(SrsCodecAudio ac)
{
acodec = ac;
return ERROR_SUCCESS;
}
int SrsTSMuxer::write_audio(SrsTsMessage* audio)
int SrsTsMuxer::write_audio(SrsTsMessage* audio)
{
int ret = ERROR_SUCCESS;
@ -2762,7 +2762,7 @@ int SrsTSMuxer::write_audio(SrsTsMessage* audio)
return ret;
}
int SrsTSMuxer::write_video(SrsTsMessage* video)
int SrsTsMuxer::write_video(SrsTsMessage* video)
{
int ret = ERROR_SUCCESS;
@ -2778,12 +2778,12 @@ int SrsTSMuxer::write_video(SrsTsMessage* video)
return ret;
}
void SrsTSMuxer::close()
void SrsTsMuxer::close()
{
writer->close();
}
SrsCodecVideo SrsTSMuxer::video_codec()
SrsCodecVideo SrsTsMuxer::video_codec()
{
return vcodec;
}
@ -2800,7 +2800,7 @@ SrsTsCache::~SrsTsCache()
srs_freep(video);
}
int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample)
int SrsTsCache::cache_audio(SrsAudioFrame* frame, int64_t dts)
{
int ret = ERROR_SUCCESS;
@ -2817,16 +2817,16 @@ int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample*
audio->sid = SrsTsPESStreamIdAudioCommon;
// must be aac or mp3
SrsCodecAudio acodec = (SrsCodecAudio)codec->audio_codec_id;
srs_assert(acodec == SrsCodecAudioAAC || acodec == SrsCodecAudioMP3);
SrsAudioCodec* acodec = frame->acodec();
srs_assert(acodec->id == SrsCodecAudioAAC || acodec->id == SrsCodecAudioMP3);
// write video to cache.
if (codec->audio_codec_id == SrsCodecAudioAAC) {
if ((ret = do_cache_aac(codec, sample)) != ERROR_SUCCESS) {
if (acodec->id == SrsCodecAudioAAC) {
if ((ret = do_cache_aac(frame)) != ERROR_SUCCESS) {
return ret;
}
} else {
if ((ret = do_cache_mp3(codec, sample)) != ERROR_SUCCESS) {
if ((ret = do_cache_mp3(frame)) != ERROR_SUCCESS) {
return ret;
}
}
@ -2834,52 +2834,55 @@ int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample*
return ret;
}
int SrsTsCache::cache_video(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample)
int SrsTsCache::cache_video(SrsVideoFrame* frame, int64_t dts)
{
int ret = ERROR_SUCCESS;
// create the ts video message.
if (!video) {
video = new SrsTsMessage();
video->write_pcr = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;
video->write_pcr = (frame->frame_type == SrsCodecVideoAVCFrameKeyFrame);
video->start_pts = dts;
}
video->dts = dts;
video->pts = video->dts + sample->cts * 90;
video->pts = video->dts + frame->cts * 90;
video->sid = SrsTsPESStreamIdVideoCommon;
// write video to cache.
if ((ret = do_cache_avc(codec, sample)) != ERROR_SUCCESS) {
if ((ret = do_cache_avc(frame)) != ERROR_SUCCESS) {
return ret;
}
return ret;
}
int SrsTsCache::do_cache_mp3(SrsAvcAacCodec* codec, SrsCodecSample* sample)
int SrsTsCache::do_cache_mp3(SrsAudioFrame* frame)
{
int ret = ERROR_SUCCESS;
// for mp3, directly write to cache.
// TODO: FIXME: implements the ts jitter.
for (int i = 0; i < sample->nb_sample_units; i++) {
SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];
audio->payload->append(sample_unit->bytes, sample_unit->size);
for (int i = 0; i < frame->nb_samples; i++) {
SrsSample* sample = &frame->samples[i];
audio->payload->append(sample->bytes, sample->size);
}
return ret;
}
int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample)
int SrsTsCache::do_cache_aac(SrsAudioFrame* frame)
{
int ret = ERROR_SUCCESS;
for (int i = 0; i < sample->nb_sample_units; i++) {
SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];
int32_t size = sample_unit->size;
SrsAudioCodec* codec = frame->acodec();
srs_assert(codec);
for (int i = 0; i < frame->nb_samples; i++) {
SrsSample* sample = &frame->samples[i];
int32_t size = sample->size;
if (!sample_unit->bytes || size <= 0 || size > 0x1fff) {
if (!sample->bytes || size <= 0 || size > 0x1fff) {
ret = ERROR_HLS_AAC_FRAME_LENGTH;
srs_error("invalid aac frame length=%d, ret=%d", size, ret);
return ret;
@ -2933,7 +2936,7 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample)
// copy to audio buffer
audio->payload->append((const char*)adts_header, sizeof(adts_header));
audio->payload->append(sample_unit->bytes, sample_unit->size);
audio->payload->append(sample->bytes, sample->size);
}
return ret;
@ -2995,7 +2998,7 @@ void srs_avc_insert_aud(SrsSimpleStream* payload, bool& aud_inserted)
}
}
int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
int SrsTsCache::do_cache_avc(SrsVideoFrame* frame)
{
int ret = ERROR_SUCCESS;
@ -3003,7 +3006,7 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
bool aud_inserted = false;
// Insert a default AUD NALU when no AUD in samples.
if (!sample->has_aud) {
if (!frame->has_aud) {
// the aud(access unit delimiter) before each frame.
// 7.3.2.4 Access unit delimiter RBSP syntax
// ISO_IEC_14496-10-AVC-2012.pdf, page 66.
@ -3039,12 +3042,15 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
video->payload->append((const char*)default_aud_nalu, 2);
}
SrsVideoCodec* codec = frame->vcodec();
srs_assert(codec);
// all sample use cont nalu header, except the sps-pps before IDR frame.
for (int i = 0; i < sample->nb_sample_units; i++) {
SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];
int32_t size = sample_unit->size;
for (int i = 0; i < frame->nb_samples; i++) {
SrsSample* sample = &frame->samples[i];
int32_t size = sample->size;
if (!sample_unit->bytes || size <= 0) {
if (!sample->bytes || size <= 0) {
ret = ERROR_HLS_AVC_SAMPLE_SIZE;
srs_error("invalid avc sample length=%d, ret=%d", size, ret);
return ret;
@ -3052,11 +3058,11 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
// 5bits, 7.3.1 NAL unit syntax,
// ISO_IEC_14496-10-AVC-2012.pdf, page 83.
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample_unit->bytes[0] & 0x1f);
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample->bytes[0] & 0x1f);
// Insert sps/pps before IDR when there is no sps/pps in samples.
// The sps/pps is parsed from sequence header(generally the first flv packet).
if (nal_unit_type == SrsAvcNaluTypeIDR && !sample->has_sps_pps) {
if (nal_unit_type == SrsAvcNaluTypeIDR && !frame->has_sps_pps) {
if (codec->sequenceParameterSetLength > 0) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength);
@ -3069,7 +3075,7 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
// Insert the NALU to video in annexb.
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(sample_unit->bytes, sample_unit->size);
video->payload->append(sample->bytes, sample->size);
}
return ret;
@ -3078,8 +3084,7 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
SrsTsEncoder::SrsTsEncoder()
{
writer = NULL;
codec = new SrsAvcAacCodec();
sample = new SrsCodecSample();
format = new SrsFormat();
cache = new SrsTsCache();
context = new SrsTsContext();
muxer = NULL;
@ -3087,8 +3092,7 @@ SrsTsEncoder::SrsTsEncoder()
SrsTsEncoder::~SrsTsEncoder()
{
srs_freep(codec);
srs_freep(sample);
srs_freep(format);
srs_freep(cache);
srs_freep(muxer);
srs_freep(context);
@ -3098,6 +3102,10 @@ int SrsTsEncoder::initialize(SrsFileWriter* fw)
{
int ret = ERROR_SUCCESS;
if ((ret = format->initialize()) != ERROR_SUCCESS) {
return ret;
}
srs_assert(fw);
if (!fw->is_open()) {
@ -3109,7 +3117,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fw)
writer = fw;
srs_freep(muxer);
muxer = new SrsTSMuxer(fw, context, SrsCodecAudioAAC, SrsCodecVideoAVC);
muxer = new SrsTsMuxer(fw, context, SrsCodecAudioAAC, SrsCodecVideoAVC);
if ((ret = muxer->open("")) != ERROR_SUCCESS) {
return ret;
@ -3122,32 +3130,24 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size)
{
int ret = ERROR_SUCCESS;
sample->clear();
if ((ret = codec->audio_aac_demux(data, size, sample)) != ERROR_SUCCESS) {
if (ret != ERROR_HLS_TRY_MP3) {
srs_error("http: ts aac demux audio failed. ret=%d", ret);
return ret;
}
if ((ret = codec->audio_mp3_demux(data, size, sample)) != ERROR_SUCCESS) {
srs_error("http: ts mp3 demux audio failed. ret=%d", ret);
return ret;
}
if ((ret = format->on_audio(timestamp, data, size)) != ERROR_SUCCESS) {
return ret;
}
SrsCodecAudio acodec = (SrsCodecAudio)codec->audio_codec_id;
// ts support audio codec: aac/mp3
if (acodec != SrsCodecAudioAAC && acodec != SrsCodecAudioMP3) {
srs_assert(format->acodec && format->audio);
if (format->acodec->id != SrsCodecAudioAAC && format->acodec->id != SrsCodecAudioMP3) {
return ret;
}
// when codec changed, write new header.
if ((ret = muxer->update_acodec(acodec)) != ERROR_SUCCESS) {
if ((ret = muxer->update_acodec(format->acodec->id)) != ERROR_SUCCESS) {
srs_error("http: ts audio write header failed. ret=%d", ret);
return ret;
}
// for aac: ignore sequence header
if (acodec == SrsCodecAudioAAC && sample->aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
if (format->acodec->id == SrsCodecAudioAAC && format->audio->aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
return ret;
}
@ -3157,7 +3157,7 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size)
int64_t dts = timestamp * 90;
// write audio to cache.
if ((ret = cache->cache_audio(codec, dts, sample)) != ERROR_SUCCESS) {
if ((ret = cache->cache_audio(format->audio, dts)) != ERROR_SUCCESS) {
return ret;
}
@ -3172,32 +3172,31 @@ int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size)
{
int ret = ERROR_SUCCESS;
sample->clear();
if ((ret = codec->video_avc_demux(data, size, sample)) != ERROR_SUCCESS) {
srs_error("http: ts codec demux video failed. ret=%d", ret);
if ((ret = format->on_video(timestamp, data, size)) != ERROR_SUCCESS) {
return ret;
}
// ignore info frame,
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
if (sample->frame_type == SrsCodecVideoAVCFrameVideoInfoFrame) {
srs_assert(format->video && format->vcodec);
if (format->video->frame_type == SrsCodecVideoAVCFrameVideoInfoFrame) {
return ret;
}
if (codec->video_codec_id != SrsCodecVideoAVC) {
if (format->vcodec->id != SrsCodecVideoAVC) {
return ret;
}
// ignore sequence header
if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame
&& sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
if (format->video->frame_type == SrsCodecVideoAVCFrameKeyFrame
&& format->video->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
return ret;
}
int64_t dts = timestamp * 90;
// write video to cache.
if ((ret = cache->cache_video(codec, dts, sample)) != ERROR_SUCCESS) {
if ((ret = cache->cache_video(format->video, dts)) != ERROR_SUCCESS) {
return ret;
}

View file

@ -42,8 +42,7 @@ class SrsTsCache;
class SrsTSMuxer;
class SrsFileWriter;
class SrsFileReader;
class SrsAvcAacCodec;
class SrsCodecSample;
class SrsFormat;
class SrsSimpleStream;
class SrsTsAdaptationField;
class SrsTsPayload;
@ -1560,7 +1559,7 @@ protected:
* write data from frame(header info) and buffer(data) to ts file.
* it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter
*/
class SrsTSMuxer
class SrsTsMuxer
{
private:
SrsCodecVideo vcodec;
@ -1570,8 +1569,8 @@ private:
SrsFileWriter* writer;
std::string path;
public:
SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc);
virtual ~SrsTSMuxer();
SrsTsMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc);
virtual ~SrsTsMuxer();
public:
/**
* open the writer, donot write the PSI of ts.
@ -1585,6 +1584,7 @@ public:
* @remark for audio aac codec, for example, SRS1, it's ok to write PSI when open ts.
* @see https://github.com/ossrs/srs/issues/301
*/
// TODO: FIXME: Remove it.
virtual int update_acodec(SrsCodecAudio ac);
/**
* write an audio frame to ts,
@ -1628,29 +1628,29 @@ public:
/**
* write audio to cache
*/
virtual int cache_audio(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample);
virtual int cache_audio(SrsAudioFrame* frame, int64_t dts);
/**
* write video to muxer.
*/
virtual int cache_video(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample);
virtual int cache_video(SrsVideoFrame* frame, int64_t dts);
private:
virtual int do_cache_mp3(SrsAvcAacCodec* codec, SrsCodecSample* sample);
virtual int do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample);
virtual int do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample);
virtual int do_cache_mp3(SrsAudioFrame* frame);
virtual int do_cache_aac(SrsAudioFrame* frame);
virtual int do_cache_avc(SrsVideoFrame* frame);
};
/**
* encode data to ts file.
*/
// TODO: FIXME: Rename it.
class SrsTsEncoder
{
private:
SrsFileWriter* writer;
private:
SrsAvcAacCodec* codec;
SrsCodecSample* sample;
SrsFormat* format;
SrsTsCache* cache;
SrsTSMuxer* muxer;
SrsTsMuxer* muxer;
SrsTsContext* context;
public:
SrsTsEncoder();