refine codec, extract avc aac codec to app.

pull/133/head
winlin 11 years ago
parent 3dbe8ba9de
commit 6286759eaa

2
trunk/configure vendored

@ -469,7 +469,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke
"srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config"
"srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks"
"srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
"srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client")
"srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_avc_aac")
APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
APP_OBJS="${MODULE_OBJS[@]}"
#

@ -0,0 +1,453 @@
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_app_avc_aac.hpp>
#include <stdlib.h>
#include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp>
#include <srs_kernel_codec.hpp>
#include <srs_kernel_stream.hpp>
SrsCodecBuffer::SrsCodecBuffer()
{
size = 0;
bytes = NULL;
}
void SrsCodecBuffer::append(void* data, int len)
{
srs_assert(data);
srs_assert(len > 0);
bytes = (char*)realloc(bytes, size + len);
memcpy(bytes + size, data, len);
size += len;
}
void SrsCodecBuffer::free()
{
size = 0;
srs_freep(bytes);
}
SrsCodecSample::SrsCodecSample()
{
clear();
}
SrsCodecSample::~SrsCodecSample()
{
}
void SrsCodecSample::clear()
{
is_video = false;
nb_buffers = 0;
cts = 0;
frame_type = SrsCodecVideoAVCFrameReserved;
avc_packet_type = SrsCodecVideoAVCTypeReserved;
sound_rate = SrsCodecAudioSampleRateReserved;
sound_size = SrsCodecAudioSampleSizeReserved;
sound_type = SrsCodecAudioSoundTypeReserved;
aac_packet_type = SrsCodecAudioTypeReserved;
}
int SrsCodecSample::add_sample(char* bytes, int size)
{
int ret = ERROR_SUCCESS;
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode samples error, "
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
return ret;
}
SrsCodecBuffer* buf = &buffers[nb_buffers++];
buf->bytes = bytes;
buf->size = size;
return ret;
}
SrsAvcAacCodec::SrsAvcAacCodec()
{
width = 0;
height = 0;
duration = 0;
NAL_unit_length = 0;
frame_rate = 0;
video_data_rate = 0;
video_codec_id = 0;
audio_data_rate = 0;
audio_codec_id = 0;
avc_profile = 0;
avc_level = 0;
aac_profile = 0;
aac_sample_rate = 0;
aac_channels = 0;
avc_extra_size = 0;
avc_extra_data = NULL;
aac_extra_size = 0;
aac_extra_data = NULL;
sequenceParameterSetLength = 0;
sequenceParameterSetNALUnit = NULL;
pictureParameterSetLength = 0;
pictureParameterSetNALUnit = NULL;
stream = new SrsStream();
}
SrsAvcAacCodec::~SrsAvcAacCodec()
{
srs_freep(avc_extra_data);
srs_freep(aac_extra_data);
srs_freep(stream);
srs_freep(sequenceParameterSetNALUnit);
srs_freep(pictureParameterSetNALUnit);
}
int SrsAvcAacCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
sample->is_video = false;
if (!data || size <= 0) {
srs_trace("no audio present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
// audio decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio sound_format failed. ret=%d", ret);
return ret;
}
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;
audio_codec_id = sound_format;
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
// reset the sample rate by sequence header
static int aac_sample_rates[] = {
96000, 88200, 64000, 48000,
44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000,
7350, 0, 0, 0
};
switch (aac_sample_rates[aac_sample_rate]) {
case 11025:
sample->sound_rate = SrsCodecAudioSampleRate11025;
break;
case 22050:
sample->sound_rate = SrsCodecAudioSampleRate22050;
break;
case 44100:
sample->sound_rate = SrsCodecAudioSampleRate44100;
break;
};
// only support aac
if (audio_codec_id != SrsCodecAudioAAC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support audio aac codec. actual=%d, ret=%d", audio_codec_id, ret);
return ret;
}
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
return ret;
}
int8_t aac_packet_type = stream->read_1bytes();
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
// AudioSpecificConfig
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
aac_extra_size = stream->left();
if (aac_extra_size > 0) {
srs_freep(aac_extra_data);
aac_extra_data = new char[aac_extra_size];
memcpy(aac_extra_data, stream->current(), aac_extra_size);
}
// only need to decode the first 2bytes:
// audioObjectType, aac_profile, 5bits.
// samplingFrequencyIndex, aac_sample_rate, 4bits.
// channelConfiguration, aac_channels, 4bits
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
return ret;
}
aac_profile = stream->read_1bytes();
aac_sample_rate = stream->read_1bytes();
aac_channels = (aac_sample_rate >> 3) & 0x0f;
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
aac_profile = (aac_profile >> 3) & 0x1f;
if (aac_profile == 0 || aac_profile == 0x1f) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed, "
"adts object=%d invalid. ret=%d", aac_profile, ret);
return ret;
}
// aac_profile = audioObjectType - 1
aac_profile--;
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;
}
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
// ensure the sequence header demuxed
if (aac_extra_size <= 0 || !aac_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
return ret;
}
// Raw AAC frame data in UI8 []
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
srs_error("hls add audio sample failed. ret=%d", ret);
return ret;
}
} else {
// ignored.
}
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
return ret;
}
int SrsAvcAacCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
sample->is_video = true;
if (!data || size <= 0) {
srs_trace("no video present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
// video decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video frame_type failed. ret=%d", ret);
return ret;
}
int8_t frame_type = stream->read_1bytes();
int8_t codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
// only support h.264/avc
if (codec_id != SrsCodecVideoAVC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret);
return ret;
}
video_codec_id = codec_id;
if (!stream->require(4)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
return ret;
}
int8_t avc_packet_type = stream->read_1bytes();
int32_t composition_time = stream->read_3bytes();
// pts = dts + cts.
sample->cts = composition_time;
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
// AVCDecoderConfigurationRecord
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
avc_extra_size = stream->left();
if (avc_extra_size > 0) {
srs_freep(avc_extra_data);
avc_extra_data = new char[avc_extra_size];
memcpy(avc_extra_data, stream->current(), avc_extra_size);
}
if (!stream->require(6)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
return ret;
}
//int8_t configurationVersion = stream->read_1bytes();
//int8_t AVCProfileIndication = stream->read_1bytes();
//int8_t profile_compatibility = stream->read_1bytes();
//int8_t AVCLevelIndication = stream->read_1bytes();
stream->skip(4);
// parse the NALU size.
int8_t lengthSizeMinusOne = stream->read_1bytes();
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
// 1 sps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
int8_t numOfSequenceParameterSets = stream->read_1bytes();
numOfSequenceParameterSets &= 0x1f;
if (numOfSequenceParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
return ret;
}
sequenceParameterSetLength = stream->read_2bytes();
if (!stream->require(sequenceParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
return ret;
}
if (sequenceParameterSetLength > 0) {
srs_freep(sequenceParameterSetNALUnit);
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
stream->skip(sequenceParameterSetLength);
}
// 1 pps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
int8_t numOfPictureParameterSets = stream->read_1bytes();
numOfPictureParameterSets &= 0x1f;
if (numOfPictureParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
return ret;
}
pictureParameterSetLength = stream->read_2bytes();
if (!stream->require(pictureParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
return ret;
}
if (pictureParameterSetLength > 0) {
srs_freep(pictureParameterSetNALUnit);
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
stream->skip(pictureParameterSetLength);
}
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
// ensure the sequence header demuxed
if (avc_extra_size <= 0 || !avc_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
return ret;
}
// One or more NALUs (Full frames are required)
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
int PictureLength = stream->left();
for (int i = 0; i < PictureLength;) {
if (!stream->require(NAL_unit_length + 1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
return ret;
}
int32_t NALUnitLength = 0;
if (NAL_unit_length == 3) {
NALUnitLength = stream->read_4bytes();
} else if (NALUnitLength == 2) {
NALUnitLength = stream->read_3bytes();
} else if (NALUnitLength == 1) {
NALUnitLength = stream->read_2bytes();
} else {
NALUnitLength = stream->read_1bytes();
}
// NALUnit
if (!stream->require(NALUnitLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
return ret;
}
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
srs_error("hls add video sample failed. ret=%d", ret);
return ret;
}
stream->skip(NALUnitLength);
i += NAL_unit_length + 1 + NALUnitLength;
}
} else {
// ignored.
}
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
frame_type, video_codec_id, avc_packet_type, composition_time, size);
return ret;
}

@ -0,0 +1,198 @@
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_APP_AVC_AAC_HPP
#define SRS_APP_AVC_AAC_HPP
/*
#include <srs_app_avc_aac.hpp>
*/
#include <srs_core.hpp>
#include <srs_kernel_codec.hpp>
#define SRS_MAX_CODEC_SAMPLE 128
// Sampling rate. The following values are defined:
// 0 = 5.5 kHz = 5512 Hz
// 1 = 11 kHz = 11025 Hz
// 2 = 22 kHz = 22050 Hz
// 3 = 44 kHz = 44100 Hz
enum SrsCodecAudioSampleRate
{
SrsCodecAudioSampleRateReserved = -1,
SrsCodecAudioSampleRate5512 = 0,
SrsCodecAudioSampleRate11025 = 1,
SrsCodecAudioSampleRate22050 = 2,
SrsCodecAudioSampleRate44100 = 3,
};
// Size of each audio sample. This parameter only pertains to
// uncompressed formats. Compressed formats always decode
// to 16 bits internally.
// 0 = 8-bit samples
// 1 = 16-bit samples
enum SrsCodecAudioSampleSize
{
SrsCodecAudioSampleSizeReserved = -1,
SrsCodecAudioSampleSize8bit = 0,
SrsCodecAudioSampleSize16bit = 1,
};
// Mono or stereo sound
// 0 = Mono sound
// 1 = Stereo sound
enum SrsCodecAudioSoundType
{
SrsCodecAudioSoundTypeReserved = -1,
SrsCodecAudioSoundTypeMono = 0,
SrsCodecAudioSoundTypeStereo = 1,
};
/**
* buffer indicates the position and size.
*/
class SrsCodecBuffer
{
public:
/**
* @remark user must manage the bytes.
*/
int size;
char* bytes;
SrsCodecBuffer();
void append(void* data, int len);
/**
* free the bytes,
* user can invoke it to free the bytes,
* the SrsCodecBuffer never free automatically.
*/
void free();
};
/**
* the samples in the flv audio/video packet.
*/
class SrsCodecSample
{
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_buffers;
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
public:
bool is_video;
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
// cts = pts - dts, where dts = flvheader->timestamp.
int32_t cts;
public:
// video specified
SrsCodecVideoAVCFrame frame_type;
SrsCodecVideoAVCType avc_packet_type;
public:
// audio specified
SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type;
public:
SrsCodecSample();
virtual ~SrsCodecSample();
void clear();
int add_sample(char* bytes, int size);
};
/**
* the h264/avc and aac codec, for media stream.
* to decode the stream of avc/aac for hls.
*/
class SrsAvcAacCodec
{
private:
SrsStream* stream;
public:
/**
* video specified
*/
// @see: SrsCodecVideo
int video_codec_id;
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_profile;
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_level;
int width;
int height;
int video_data_rate; // in bps
int frame_rate;
int duration;
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
int8_t NAL_unit_length;
u_int16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit;
u_int16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit;
public:
/**
* audio specified
*/
// @see: SrsCodecAudioType
int audio_codec_id;
int audio_data_rate; // in bps
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
u_int8_t aac_profile;
// samplingFrequencyIndex
u_int8_t aac_sample_rate;
// channelConfiguration
u_int8_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;
public:
SrsAvcAacCodec();
virtual ~SrsAvcAacCodec();
// the following function used for hls to build the codec info.
public:
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
};
#endif

@ -228,9 +228,9 @@ int SrsDvrPlan::on_video(SrsSharedPtrMessage* video)
int size = (int)video->size;
#ifdef SRS_AUTO_HTTP_CALLBACK
bool is_key_frame = SrsCodec::video_is_h264((int8_t*)payload, size)
&& SrsCodec::video_is_keyframe((int8_t*)payload, size)
&& !SrsCodec::video_is_sequence_header((int8_t*)payload, size);
bool is_key_frame = SrsFlvCodec::video_is_h264((int8_t*)payload, size)
&& SrsFlvCodec::video_is_keyframe((int8_t*)payload, size)
&& !SrsFlvCodec::video_is_sequence_header((int8_t*)payload, size);
if (is_key_frame) {
segment->has_keyframe = true;
if ((ret = on_video_keyframe()) != ERROR_SUCCESS) {

@ -44,6 +44,7 @@ using namespace std;
#include <srs_protocol_rtmp.hpp>
#include <srs_app_pithy_print.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_app_avc_aac.hpp>
// max PES packets size to flush the video.
#define SRS_AUTO_HLS_AUDIO_CACHE_SIZE 1024 * 1024
@ -1014,7 +1015,7 @@ int SrsHlsCache::on_sequence_header(SrsHlsMuxer* muxer)
return muxer->on_sequence_header();
}
int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample)
int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
@ -1062,7 +1063,7 @@ int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, S
}
int SrsHlsCache::write_video(
SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample)
SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
@ -1123,7 +1124,7 @@ int SrsHlsCache::reap_segment(string log_desc, SrsHlsMuxer* muxer, int64_t segme
return ret;
}
int SrsHlsCache::cache_audio(SrsCodec* codec, SrsCodecSample* sample)
int SrsHlsCache::cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
@ -1190,7 +1191,7 @@ int SrsHlsCache::cache_audio(SrsCodec* codec, SrsCodecSample* sample)
return ret;
}
int SrsHlsCache::cache_video(SrsCodec* codec, SrsCodecSample* sample)
int SrsHlsCache::cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
@ -1262,7 +1263,7 @@ SrsHls::SrsHls(SrsSource* _source)
hls_enabled = false;
source = _source;
codec = new SrsCodec();
codec = new SrsAvcAacCodec();
sample = new SrsCodecSample();
jitter = new SrsRtmpJitter();

@ -41,7 +41,7 @@ class SrsMpegtsFrame;
class SrsAmf0Object;
class SrsRtmpJitter;
class SrsTSMuxer;
class SrsCodec;
class SrsAvcAacCodec;
class SrsRequest;
class SrsPithyPrint;
class SrsSource;
@ -247,11 +247,11 @@ public:
/**
* write audio to cache, if need to flush, flush to muxer.
*/
virtual int write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample);
virtual int write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample);
/**
* write video to muxer.
*/
virtual int write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample);
virtual int write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample);
private:
/**
* reopen the muxer for a new hls segment,
@ -260,8 +260,8 @@ private:
* so, user must reap_segment then flush_video to hls muxer.
*/
virtual int reap_segment(std::string log_desc, SrsHlsMuxer* muxer, int64_t segment_start_dts);
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
virtual int cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample);
virtual int cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample);
};
/**
@ -277,7 +277,7 @@ private:
private:
bool hls_enabled;
SrsSource* source;
SrsCodec* codec;
SrsAvcAacCodec* codec;
SrsCodecSample* sample;
SrsRtmpJitter* jitter;
SrsPithyPrint* pithy_print;

@ -201,7 +201,7 @@ void SrsMessageQueue::shrink()
SrsSharedPtrMessage* msg = msgs[i];
if (msg->header.is_video()) {
if (SrsCodec::video_is_keyframe(msg->payload, msg->size)) {
if (SrsFlvCodec::video_is_keyframe(msg->payload, msg->size)) {
// the max frame index to remove.
iframe_index = i;
@ -363,7 +363,7 @@ int SrsGopCache::cache(SrsSharedPtrMessage* msg)
}
// clear gop cache when got key frame
if (msg->header.is_video() && SrsCodec::video_is_keyframe(msg->payload, msg->size)) {
if (msg->header.is_video() && SrsFlvCodec::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());
@ -1012,7 +1012,7 @@ int SrsSource::on_audio(SrsMessage* audio)
// cache the sequence header if h264
// donot cache the sequence header to gop_cache, return here.
if (SrsCodec::audio_is_sequence_header(msg->payload, msg->size)) {
if (SrsFlvCodec::audio_is_sequence_header(msg->payload, msg->size)) {
srs_freep(cache_sh_audio);
cache_sh_audio = msg->copy();
srs_trace("got audio sh, size=%d", msg->header.payload_length);
@ -1102,7 +1102,7 @@ int SrsSource::on_video(SrsMessage* video)
// cache the sequence header if h264
// donot cache the sequence header to gop_cache, return here.
if (SrsCodec::video_is_sequence_header(msg->payload, msg->size)) {
if (SrsFlvCodec::video_is_sequence_header(msg->payload, msg->size)) {
srs_freep(cache_sh_video);
cache_sh_video = msg->copy();
srs_trace("got video sh, size=%d", msg->header.payload_length);

@ -31,429 +31,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_kernel_log.hpp>
#include <srs_core_autofree.hpp>
SrsCodecBuffer::SrsCodecBuffer()
SrsFlvCodec::SrsFlvCodec()
{
size = 0;
bytes = NULL;
}
void SrsCodecBuffer::append(void* data, int len)
SrsFlvCodec::~SrsFlvCodec()
{
srs_assert(data);
srs_assert(len > 0);
bytes = (char*)realloc(bytes, size + len);
memcpy(bytes + size, data, len);
size += len;
}
void SrsCodecBuffer::free()
{
size = 0;
srs_freep(bytes);
}
SrsCodecSample::SrsCodecSample()
{
clear();
}
SrsCodecSample::~SrsCodecSample()
{
}
void SrsCodecSample::clear()
{
is_video = false;
nb_buffers = 0;
cts = 0;
frame_type = SrsCodecVideoAVCFrameReserved;
avc_packet_type = SrsCodecVideoAVCTypeReserved;
sound_rate = SrsCodecAudioSampleRateReserved;
sound_size = SrsCodecAudioSampleSizeReserved;
sound_type = SrsCodecAudioSoundTypeReserved;
aac_packet_type = SrsCodecAudioTypeReserved;
}
int SrsCodecSample::add_sample(char* bytes, int size)
{
int ret = ERROR_SUCCESS;
if (nb_buffers >= SRS_MAX_CODEC_SAMPLE) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode samples error, "
"exceed the max count: %d, ret=%d", SRS_MAX_CODEC_SAMPLE, ret);
return ret;
}
SrsCodecBuffer* buf = &buffers[nb_buffers++];
buf->bytes = bytes;
buf->size = size;
return ret;
}
SrsCodec::SrsCodec()
{
width = 0;
height = 0;
duration = 0;
NAL_unit_length = 0;
frame_rate = 0;
video_data_rate = 0;
video_codec_id = 0;
audio_data_rate = 0;
audio_codec_id = 0;
avc_profile = 0;
avc_level = 0;
aac_profile = 0;
aac_sample_rate = 0;
aac_channels = 0;
avc_extra_size = 0;
avc_extra_data = NULL;
aac_extra_size = 0;
aac_extra_data = NULL;
sequenceParameterSetLength = 0;
sequenceParameterSetNALUnit = NULL;
pictureParameterSetLength = 0;
pictureParameterSetNALUnit = NULL;
stream = new SrsStream();
}
SrsCodec::~SrsCodec()
{
srs_freep(avc_extra_data);
srs_freep(aac_extra_data);
srs_freep(stream);
srs_freep(sequenceParameterSetNALUnit);
srs_freep(pictureParameterSetNALUnit);
}
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
sample->is_video = false;
if (!data || size <= 0) {
srs_trace("no audio present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
// audio decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio sound_format failed. ret=%d", ret);
return ret;
}
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;
audio_codec_id = sound_format;
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
// reset the sample rate by sequence header
static int aac_sample_rates[] = {
96000, 88200, 64000, 48000,
44100, 32000, 24000, 22050,
16000, 12000, 11025, 8000,
7350, 0, 0, 0
};
switch (aac_sample_rates[aac_sample_rate]) {
case 11025:
sample->sound_rate = SrsCodecAudioSampleRate11025;
break;
case 22050:
sample->sound_rate = SrsCodecAudioSampleRate22050;
break;
case 44100:
sample->sound_rate = SrsCodecAudioSampleRate44100;
break;
};
// only support aac
if (audio_codec_id != SrsCodecAudioAAC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support audio aac codec. actual=%d, ret=%d", audio_codec_id, ret);
return ret;
}
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac_packet_type failed. ret=%d", ret);
return ret;
}
int8_t aac_packet_type = stream->read_1bytes();
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
// AudioSpecificConfig
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
aac_extra_size = stream->left();
if (aac_extra_size > 0) {
srs_freep(aac_extra_data);
aac_extra_data = new char[aac_extra_size];
memcpy(aac_extra_data, stream->current(), aac_extra_size);
}
// only need to decode the first 2bytes:
// audioObjectType, aac_profile, 5bits.
// samplingFrequencyIndex, aac_sample_rate, 4bits.
// channelConfiguration, aac_channels, 4bits
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
return ret;
}
aac_profile = stream->read_1bytes();
aac_sample_rate = stream->read_1bytes();
aac_channels = (aac_sample_rate >> 3) & 0x0f;
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
aac_profile = (aac_profile >> 3) & 0x1f;
if (aac_profile == 0 || aac_profile == 0x1f) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac sequence header failed, "
"adts object=%d invalid. ret=%d", aac_profile, ret);
return ret;
}
// aac_profile = audioObjectType - 1
aac_profile--;
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;
}
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
// ensure the sequence header demuxed
if (aac_extra_size <= 0 || !aac_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode audio aac failed, sequence header not found. ret=%d", ret);
return ret;
}
// Raw AAC frame data in UI8 []
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
srs_error("hls add audio sample failed. ret=%d", ret);
return ret;
}
} else {
// ignored.
}
srs_info("audio decoded, type=%d, codec=%d, asize=%d, rate=%d, format=%d, size=%d",
sound_type, audio_codec_id, sound_size, sound_rate, sound_format, size);
return ret;
}
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
{
int ret = ERROR_SUCCESS;
sample->is_video = true;
if (!data || size <= 0) {
srs_trace("no video present, hls ignore it.");
return ret;
}
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
return ret;
}
// video decode
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video frame_type failed. ret=%d", ret);
return ret;
}
int8_t frame_type = stream->read_1bytes();
int8_t codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
// only support h.264/avc
if (codec_id != SrsCodecVideoAVC) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls only support video h.264/avc codec. actual=%d, ret=%d", codec_id, ret);
return ret;
}
video_codec_id = codec_id;
if (!stream->require(4)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc_packet_type failed. ret=%d", ret);
return ret;
}
int8_t avc_packet_type = stream->read_1bytes();
int32_t composition_time = stream->read_3bytes();
// pts = dts + cts.
sample->cts = composition_time;
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
// AVCDecoderConfigurationRecord
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
avc_extra_size = stream->left();
if (avc_extra_size > 0) {
srs_freep(avc_extra_data);
avc_extra_data = new char[avc_extra_size];
memcpy(avc_extra_data, stream->current(), avc_extra_size);
}
if (!stream->require(6)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header failed. ret=%d", ret);
return ret;
}
//int8_t configurationVersion = stream->read_1bytes();
//int8_t AVCProfileIndication = stream->read_1bytes();
//int8_t profile_compatibility = stream->read_1bytes();
//int8_t AVCLevelIndication = stream->read_1bytes();
stream->skip(4);
// parse the NALU size.
int8_t lengthSizeMinusOne = stream->read_1bytes();
lengthSizeMinusOne &= 0x03;
NAL_unit_length = lengthSizeMinusOne;
// 1 sps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
int8_t numOfSequenceParameterSets = stream->read_1bytes();
numOfSequenceParameterSets &= 0x1f;
if (numOfSequenceParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps size failed. ret=%d", ret);
return ret;
}
sequenceParameterSetLength = stream->read_2bytes();
if (!stream->require(sequenceParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header sps data failed. ret=%d", ret);
return ret;
}
if (sequenceParameterSetLength > 0) {
srs_freep(sequenceParameterSetNALUnit);
sequenceParameterSetNALUnit = new char[sequenceParameterSetLength];
memcpy(sequenceParameterSetNALUnit, stream->current(), sequenceParameterSetLength);
stream->skip(sequenceParameterSetLength);
}
// 1 pps
if (!stream->require(1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
int8_t numOfPictureParameterSets = stream->read_1bytes();
numOfPictureParameterSets &= 0x1f;
if (numOfPictureParameterSets != 1) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps failed. ret=%d", ret);
return ret;
}
if (!stream->require(2)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps size failed. ret=%d", ret);
return ret;
}
pictureParameterSetLength = stream->read_2bytes();
if (!stream->require(pictureParameterSetLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc sequenc header pps data failed. ret=%d", ret);
return ret;
}
if (pictureParameterSetLength > 0) {
srs_freep(pictureParameterSetNALUnit);
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
stream->skip(pictureParameterSetLength);
}
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
// ensure the sequence header demuxed
if (avc_extra_size <= 0 || !avc_extra_data) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc failed, sequence header not found. ret=%d", ret);
return ret;
}
// One or more NALUs (Full frames are required)
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
int PictureLength = stream->left();
for (int i = 0; i < PictureLength;) {
if (!stream->require(NAL_unit_length + 1)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU size failed. ret=%d", ret);
return ret;
}
int32_t NALUnitLength = 0;
if (NAL_unit_length == 3) {
NALUnitLength = stream->read_4bytes();
} else if (NALUnitLength == 2) {
NALUnitLength = stream->read_3bytes();
} else if (NALUnitLength == 1) {
NALUnitLength = stream->read_2bytes();
} else {
NALUnitLength = stream->read_1bytes();
}
// NALUnit
if (!stream->require(NALUnitLength)) {
ret = ERROR_HLS_DECODE_ERROR;
srs_error("hls decode video avc NALU data failed. ret=%d", ret);
return ret;
}
// 7.3.1 NAL unit syntax, H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
srs_error("hls add video sample failed. ret=%d", ret);
return ret;
}
stream->skip(NALUnitLength);
i += NAL_unit_length + 1 + NALUnitLength;
}
} else {
// ignored.
}
srs_info("video decoded, type=%d, codec=%d, avc=%d, time=%d, size=%d",
frame_type, video_codec_id, avc_packet_type, composition_time, size);
return ret;
}
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
bool SrsFlvCodec::video_is_keyframe(int8_t* data, int size)
{
// 2bytes required.
if (size < 1) {
@ -466,7 +52,7 @@ bool SrsCodec::video_is_keyframe(int8_t* data, int size)
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
}
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
bool SrsFlvCodec::video_is_sequence_header(int8_t* data, int size)
{
// sequence header only for h264
if (!video_is_h264(data, size)) {
@ -487,7 +73,7 @@ bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
}
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
bool SrsFlvCodec::audio_is_sequence_header(int8_t* data, int size)
{
// sequence header only for aac
if (!audio_is_aac(data, size)) {
@ -504,7 +90,7 @@ bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
}
bool SrsCodec::video_is_h264(int8_t* data, int size)
bool SrsFlvCodec::video_is_h264(int8_t* data, int size)
{
// 1bytes required.
if (size < 1) {
@ -517,7 +103,7 @@ bool SrsCodec::video_is_h264(int8_t* data, int size)
return codec_id == SrsCodecVideoAVC;
}
bool SrsCodec::audio_is_aac(int8_t* data, int size)
bool SrsFlvCodec::audio_is_aac(int8_t* data, int size)
{
// 1bytes required.
if (size < 1) {

@ -30,29 +30,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp>
#define SRS_MAX_CODEC_SAMPLE 128
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
// AACPacketType IF SoundFormat == 10 UI8
// The following values are defined:
// 0 = AAC sequence header
// 1 = AAC raw
enum SrsCodecAudioType
{
SrsCodecVideoReserved = 0,
SrsCodecVideoSorensonH263 = 2,
SrsCodecVideoScreenVideo = 3,
SrsCodecVideoOn2VP6 = 4,
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
SrsCodecVideoScreenVideoVersion2 = 6,
SrsCodecVideoAVC = 7,
SrsCodecAudioTypeReserved = -1,
SrsCodecAudioTypeSequenceHeader = 0,
SrsCodecAudioTypeRawData = 1,
};
// E.4.3.1 VIDEODATA
@ -89,6 +77,27 @@ enum SrsCodecVideoAVCType
SrsCodecVideoAVCTypeSequenceHeaderEOF = 2,
};
// 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
{
SrsCodecVideoReserved = 0,
SrsCodecVideoSorensonH263 = 2,
SrsCodecVideoScreenVideo = 3,
SrsCodecVideoOn2VP6 = 4,
SrsCodecVideoOn2VP6WithAlphaChannel = 5,
SrsCodecVideoScreenVideoVersion2 = 6,
SrsCodecVideoAVC = 7,
};
// SoundFormat UB [4]
// Format of SoundData. The following values are defined:
// 0 = Linear PCM, platform endian
@ -126,165 +135,15 @@ enum SrsCodecAudio
SrsCodecAudioReservedDeviceSpecificSound = 15,
};
// AACPacketType IF SoundFormat == 10 UI8
// The following values are defined:
// 0 = AAC sequence header
// 1 = AAC raw
enum SrsCodecAudioType
{
SrsCodecAudioTypeReserved = -1,
SrsCodecAudioTypeSequenceHeader = 0,
SrsCodecAudioTypeRawData = 1,
};
// Sampling rate. The following values are defined:
// 0 = 5.5 kHz = 5512 Hz
// 1 = 11 kHz = 11025 Hz
// 2 = 22 kHz = 22050 Hz
// 3 = 44 kHz = 44100 Hz
enum SrsCodecAudioSampleRate
{
SrsCodecAudioSampleRateReserved = -1,
SrsCodecAudioSampleRate5512 = 0,
SrsCodecAudioSampleRate11025 = 1,
SrsCodecAudioSampleRate22050 = 2,
SrsCodecAudioSampleRate44100 = 3,
};
// Size of each audio sample. This parameter only pertains to
// uncompressed formats. Compressed formats always decode
// to 16 bits internally.
// 0 = 8-bit samples
// 1 = 16-bit samples
enum SrsCodecAudioSampleSize
{
SrsCodecAudioSampleSizeReserved = -1,
SrsCodecAudioSampleSize8bit = 0,
SrsCodecAudioSampleSize16bit = 1,
};
// Mono or stereo sound
// 0 = Mono sound
// 1 = Stereo sound
enum SrsCodecAudioSoundType
{
SrsCodecAudioSoundTypeReserved = -1,
SrsCodecAudioSoundTypeMono = 0,
SrsCodecAudioSoundTypeStereo = 1,
};
/**
* buffer indicates the position and size.
*/
class SrsCodecBuffer
{
public:
/**
* @remark user must manage the bytes.
*/
int size;
char* bytes;
SrsCodecBuffer();
void append(void* data, int len);
/**
* free the bytes,
* user can invoke it to free the bytes,
* the SrsCodecBuffer never free automatically.
*/
void free();
};
/**
* the samples in the flv audio/video packet.
*/
class SrsCodecSample
{
public:
int nb_buffers;
SrsCodecBuffer buffers[SRS_MAX_CODEC_SAMPLE];
public:
bool is_video;
// video specified
SrsCodecVideoAVCFrame frame_type;
SrsCodecVideoAVCType avc_packet_type;
// CompositionTime, video_file_format_spec_v10_1.pdf, page 78.
// cts = pts - dts, where dts = flvheader->timestamp.
int32_t cts;
// audio specified
SrsCodecAudioSampleRate sound_rate;
SrsCodecAudioSampleSize sound_size;
SrsCodecAudioSoundType sound_type;
SrsCodecAudioType aac_packet_type;
public:
SrsCodecSample();
virtual ~SrsCodecSample();
void clear();
int add_sample(char* bytes, int size);
};
/**
* Annex E. The FLV File Format
* @see SrsAvcAacCodec for the media stream codec.
*/
class SrsCodec
class SrsFlvCodec
{
private:
SrsStream* stream;
public:
/**
* video specified
*/
// @see: SrsCodecVideo
int video_codec_id;
// profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_profile;
// level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
u_int8_t avc_level;
int width;
int height;
int video_data_rate; // in bps
int frame_rate;
int duration;
// lengthSizeMinusOne, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
int8_t NAL_unit_length;
u_int16_t sequenceParameterSetLength;
char* sequenceParameterSetNALUnit;
u_int16_t pictureParameterSetLength;
char* pictureParameterSetNALUnit;
/**
* audio specified
*/
// @see: SrsCodecAudioType
int audio_codec_id;
int audio_data_rate; // in bps
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
// audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
u_int8_t aac_profile;
// samplingFrequencyIndex
u_int8_t aac_sample_rate;
// channelConfiguration
u_int8_t aac_channels;
// 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;
public:
SrsCodec();
virtual ~SrsCodec();
// the following function used for hls to build the codec info.
public:
virtual int audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample);
virtual int video_avc_demux(int8_t* data, int size, SrsCodecSample* sample);
SrsFlvCodec();
virtual ~SrsFlvCodec();
// the following function used to finger out the flv/rtmp packet detail.
public:
/**

@ -540,12 +540,12 @@ flv_bool srs_flv_is_eof(int error_code)
flv_bool srs_flv_is_sequence_header(char* data, int32_t size)
{
return SrsCodec::video_is_sequence_header((int8_t*)data, (int)size);
return SrsFlvCodec::video_is_sequence_header((int8_t*)data, (int)size);
}
flv_bool srs_flv_is_keyframe(char* data, int32_t size)
{
return SrsCodec::video_is_keyframe((int8_t*)data, (int)size);
return SrsFlvCodec::video_is_keyframe((int8_t*)data, (int)size);
}
srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed)

@ -43,6 +43,8 @@ file
..\rtmp\srs_protocol_utility.hpp,
..\rtmp\srs_protocol_utility.cpp,
app readonly separator,
..\app\srs_app_avc_aac.hpp,
..\app\srs_app_avc_aac.cpp,
..\app\srs_app_bandwidth.hpp,
..\app\srs_app_bandwidth.cpp,
..\app\srs_app_conn.hpp,

Loading…
Cancel
Save