2013-11-23 03:36:07 +00:00
|
|
|
/*
|
|
|
|
The MIT License (MIT)
|
|
|
|
|
2014-01-01 02:37:12 +00:00
|
|
|
Copyright (c) 2013-2014 winlin
|
2013-11-23 03:36:07 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2014-03-02 13:49:09 +00:00
|
|
|
#include <srs_app_codec.hpp>
|
2013-11-23 03:36:07 +00:00
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
#include <string.h>
|
2013-11-24 15:13:14 +00:00
|
|
|
#include <stdlib.h>
|
2013-11-24 06:28:58 +00:00
|
|
|
|
2014-03-01 02:30:16 +00:00
|
|
|
#include <srs_kernel_error.hpp>
|
2014-03-01 02:58:13 +00:00
|
|
|
#include <srs_kernel_stream.hpp>
|
2014-03-01 02:42:55 +00:00
|
|
|
#include <srs_kernel_log.hpp>
|
2013-11-24 07:08:43 +00:00
|
|
|
#include <srs_core_autofree.hpp>
|
2013-11-24 04:39:47 +00:00
|
|
|
|
2013-11-24 15:13:14 +00:00
|
|
|
SrsCodecBuffer::SrsCodecBuffer()
|
|
|
|
{
|
|
|
|
size = 0;
|
|
|
|
bytes = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsCodecBuffer::append(void* data, int len)
|
|
|
|
{
|
|
|
|
srs_assert(data);
|
|
|
|
srs_assert(len > 0);
|
2013-11-28 06:53:46 +00:00
|
|
|
|
2013-11-24 15:13:14 +00:00
|
|
|
bytes = (char*)realloc(bytes, size + len);
|
|
|
|
memcpy(bytes + size, data, len);
|
|
|
|
size += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsCodecBuffer::free()
|
|
|
|
{
|
|
|
|
size = 0;
|
|
|
|
srs_freepa(bytes);
|
|
|
|
}
|
|
|
|
|
2013-11-24 08:00:45 +00:00
|
|
|
SrsCodecSample::SrsCodecSample()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
SrsCodecSample::~SrsCodecSample()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void SrsCodecSample::clear()
|
|
|
|
{
|
2013-11-24 09:53:36 +00:00
|
|
|
is_video = false;
|
2013-11-24 08:00:45 +00:00
|
|
|
nb_buffers = 0;
|
2013-11-24 09:53:36 +00:00
|
|
|
|
|
|
|
cts = 0;
|
|
|
|
frame_type = SrsCodecVideoAVCFrameReserved;
|
|
|
|
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
2013-11-24 10:55:39 +00:00
|
|
|
|
|
|
|
sound_rate = SrsCodecAudioSampleRateReserved;
|
|
|
|
sound_size = SrsCodecAudioSampleSizeReserved;
|
|
|
|
sound_type = SrsCodecAudioSoundTypeReserved;
|
|
|
|
aac_packet_type = SrsCodecAudioTypeReserved;
|
2013-11-24 08:00:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-11-23 03:36:07 +00:00
|
|
|
SrsCodec::SrsCodec()
|
|
|
|
{
|
2013-11-24 04:39:47 +00:00
|
|
|
width = 0;
|
|
|
|
height = 0;
|
|
|
|
duration = 0;
|
2013-11-24 07:08:43 +00:00
|
|
|
NAL_unit_length = 0;
|
2013-11-24 04:39:47 +00:00
|
|
|
frame_rate = 0;
|
|
|
|
video_data_rate = 0;
|
|
|
|
video_codec_id = 0;
|
|
|
|
audio_data_rate = 0;
|
|
|
|
audio_codec_id = 0;
|
2013-11-24 15:13:14 +00:00
|
|
|
avc_profile = 0;
|
|
|
|
avc_level = 0;
|
|
|
|
aac_profile = 0;
|
|
|
|
aac_sample_rate = 0;
|
|
|
|
aac_channels = 0;
|
2013-11-24 04:39:47 +00:00
|
|
|
avc_extra_size = 0;
|
|
|
|
avc_extra_data = NULL;
|
|
|
|
aac_extra_size = 0;
|
|
|
|
aac_extra_data = NULL;
|
2013-11-25 15:54:01 +00:00
|
|
|
sequenceParameterSetLength = 0;
|
|
|
|
sequenceParameterSetNALUnit = NULL;
|
|
|
|
pictureParameterSetLength = 0;
|
|
|
|
pictureParameterSetNALUnit = NULL;
|
2013-11-24 04:39:47 +00:00
|
|
|
|
|
|
|
stream = new SrsStream();
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SrsCodec::~SrsCodec()
|
|
|
|
{
|
2013-11-24 04:39:47 +00:00
|
|
|
srs_freepa(avc_extra_data);
|
|
|
|
srs_freepa(aac_extra_data);
|
|
|
|
|
|
|
|
srs_freep(stream);
|
2013-11-25 15:54:01 +00:00
|
|
|
srs_freepa(sequenceParameterSetNALUnit);
|
|
|
|
srs_freepa(pictureParameterSetNALUnit);
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
2013-11-24 08:00:45 +00:00
|
|
|
int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
|
2013-11-23 03:36:07 +00:00
|
|
|
{
|
2013-11-24 04:39:47 +00:00
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2013-11-24 09:53:36 +00:00
|
|
|
sample->is_video = false;
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
if (!data || size <= 0) {
|
2013-11-24 06:28:58 +00:00
|
|
|
srs_trace("no audio present, hls ignore it.");
|
2013-11-24 04:39:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = stream->initialize((char*)data, size)) != ERROR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
2013-11-24 06:28:58 +00:00
|
|
|
|
|
|
|
// audio decode
|
|
|
|
if (!stream->require(1)) {
|
|
|
|
ret = ERROR_HLS_DECODE_ERROR;
|
|
|
|
srs_error("hls decode audio sound_format failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-11-24 04:39:47 +00:00
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
int8_t sound_format = stream->read_1bytes();
|
|
|
|
|
2013-11-24 10:55:39 +00:00
|
|
|
int8_t sound_type = sound_format & 0x01;
|
|
|
|
int8_t sound_size = (sound_format >> 1) & 0x01;
|
2013-11-27 09:30:16 +00:00
|
|
|
int8_t sound_rate = (sound_format >> 2) & 0x03;
|
2013-11-24 06:28:58 +00:00
|
|
|
sound_format = (sound_format >> 4) & 0x0f;
|
|
|
|
|
|
|
|
audio_codec_id = sound_format;
|
2013-11-24 10:55:39 +00:00
|
|
|
sample->sound_type = (SrsCodecAudioSoundType)sound_type;
|
|
|
|
sample->sound_rate = (SrsCodecAudioSampleRate)sound_rate;
|
|
|
|
sample->sound_size = (SrsCodecAudioSampleSize)sound_size;
|
2013-11-24 06:28:58 +00:00
|
|
|
|
2013-11-27 09:30:16 +00:00
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
// only support aac
|
|
|
|
if (audio_codec_id != SrsCodecAudioAAC) {
|
|
|
|
ret = ERROR_HLS_DECODE_ERROR;
|
|
|
|
srs_error("hls only support audio aac codec. ret=%d", 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();
|
2013-11-24 10:55:39 +00:00
|
|
|
sample->aac_packet_type = (SrsCodecAudioType)aac_packet_type;
|
2013-11-24 06:28:58 +00:00
|
|
|
|
|
|
|
if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
|
|
|
|
// AudioSpecificConfig
|
|
|
|
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
2013-11-24 08:00:45 +00:00
|
|
|
aac_extra_size = stream->left();
|
2013-11-24 06:28:58 +00:00
|
|
|
if (aac_extra_size > 0) {
|
|
|
|
srs_freepa(aac_extra_data);
|
|
|
|
aac_extra_data = new char[aac_extra_size];
|
2013-11-24 08:00:45 +00:00
|
|
|
memcpy(aac_extra_data, stream->current(), aac_extra_size);
|
2013-11-24 04:39:47 +00:00
|
|
|
}
|
2013-11-24 15:13:14 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2013-11-24 06:28:58 +00:00
|
|
|
} else if (aac_packet_type == SrsCodecAudioTypeRawData) {
|
2013-11-24 07:11:18 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
// Raw AAC frame data in UI8 []
|
2013-11-24 07:08:43 +00:00
|
|
|
// 6.3 Raw Data, aac-iso-13818-7.pdf, page 28
|
2013-11-24 08:00:45 +00:00
|
|
|
if ((ret = sample->add_sample(stream->current(), stream->left())) != ERROR_SUCCESS) {
|
|
|
|
srs_error("hls add audio sample failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-11-24 06:28:58 +00:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
2013-11-24 08:00:45 +00:00
|
|
|
int SrsCodec::video_avc_demux(int8_t* data, int size, SrsCodecSample* sample)
|
2013-11-24 06:28:58 +00:00
|
|
|
{
|
|
|
|
int ret = ERROR_SUCCESS;
|
|
|
|
|
2013-11-24 09:53:36 +00:00
|
|
|
sample->is_video = true;
|
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
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;
|
|
|
|
|
2013-11-24 09:53:36 +00:00
|
|
|
sample->frame_type = (SrsCodecVideoAVCFrame)frame_type;
|
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
// only support h.264/avc
|
|
|
|
if (codec_id != SrsCodecVideoAVC) {
|
|
|
|
ret = ERROR_HLS_DECODE_ERROR;
|
|
|
|
srs_error("hls only support video h.264/avc codec. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-11-24 09:53:36 +00:00
|
|
|
video_codec_id = codec_id;
|
2013-11-24 06:28:58 +00:00
|
|
|
|
|
|
|
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();
|
|
|
|
|
2013-11-24 08:00:45 +00:00
|
|
|
// pts = dts + cts.
|
|
|
|
sample->cts = composition_time;
|
2013-11-24 09:53:36 +00:00
|
|
|
sample->avc_packet_type = (SrsCodecVideoAVCType)avc_packet_type;
|
2013-11-24 06:28:58 +00:00
|
|
|
|
|
|
|
if (avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) {
|
|
|
|
// AVCDecoderConfigurationRecord
|
|
|
|
// 5.2.4.1.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
|
2013-11-24 08:00:45 +00:00
|
|
|
avc_extra_size = stream->left();
|
2013-11-24 06:28:58 +00:00
|
|
|
if (avc_extra_size > 0) {
|
|
|
|
srs_freepa(avc_extra_data);
|
|
|
|
avc_extra_data = new char[avc_extra_size];
|
2013-11-24 08:00:45 +00:00
|
|
|
memcpy(avc_extra_data, stream->current(), avc_extra_size);
|
2013-11-24 04:39:47 +00:00
|
|
|
}
|
2013-11-24 07:08:43 +00:00
|
|
|
|
|
|
|
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;
|
2013-11-25 15:54:01 +00:00
|
|
|
|
|
|
|
// 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_freepa(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_freepa(pictureParameterSetNALUnit);
|
|
|
|
pictureParameterSetNALUnit = new char[pictureParameterSetLength];
|
|
|
|
memcpy(pictureParameterSetNALUnit, stream->current(), pictureParameterSetLength);
|
|
|
|
stream->skip(pictureParameterSetLength);
|
|
|
|
}
|
2013-11-24 06:28:58 +00:00
|
|
|
} else if (avc_packet_type == SrsCodecVideoAVCTypeNALU){
|
2013-11-24 07:11:18 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
// One or more NALUs (Full frames are required)
|
|
|
|
// 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 20
|
2013-11-24 08:00:45 +00:00
|
|
|
int PictureLength = stream->left();
|
2013-11-24 07:08:43 +00:00
|
|
|
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.
|
2013-11-24 08:00:45 +00:00
|
|
|
if ((ret = sample->add_sample(stream->current(), NALUnitLength)) != ERROR_SUCCESS) {
|
|
|
|
srs_error("hls add video sample failed. ret=%d", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2013-11-24 07:08:43 +00:00
|
|
|
stream->skip(NALUnitLength);
|
|
|
|
|
|
|
|
i += NAL_unit_length + 1 + NALUnitLength;
|
|
|
|
}
|
2013-11-24 04:39:47 +00:00
|
|
|
} else {
|
2013-11-24 06:28:58 +00:00
|
|
|
// ignored.
|
2013-11-24 04:39:47 +00:00
|
|
|
}
|
2013-11-23 03:36:07 +00:00
|
|
|
|
2013-11-24 06:28:58 +00:00
|
|
|
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);
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SrsCodec::video_is_keyframe(int8_t* data, int size)
|
|
|
|
{
|
2013-11-23 03:36:07 +00:00
|
|
|
// 2bytes required.
|
|
|
|
if (size < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char frame_type = *(char*)data;
|
|
|
|
frame_type = (frame_type >> 4) & 0x0F;
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
return frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
|
|
|
|
{
|
|
|
|
// sequence header only for h264
|
|
|
|
if (!video_is_h264(data, size)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2bytes required.
|
|
|
|
if (size < 2) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char frame_type = *(char*)data;
|
|
|
|
frame_type = (frame_type >> 4) & 0x0F;
|
|
|
|
|
|
|
|
char avc_packet_type = *(char*)(data + 1);
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
return frame_type == SrsCodecVideoAVCFrameKeyFrame
|
|
|
|
&& avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SrsCodec::audio_is_sequence_header(int8_t* data, int size)
|
|
|
|
{
|
|
|
|
// sequence header only for aac
|
|
|
|
if (!audio_is_aac(data, size)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2bytes required.
|
|
|
|
if (size < 2) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char aac_packet_type = *(char*)(data + 1);
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
return aac_packet_type == SrsCodecAudioTypeSequenceHeader;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SrsCodec::video_is_h264(int8_t* data, int size)
|
|
|
|
{
|
|
|
|
// 1bytes required.
|
|
|
|
if (size < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char codec_id = *(char*)data;
|
|
|
|
codec_id = codec_id & 0x0F;
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
return codec_id == SrsCodecVideoAVC;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SrsCodec::audio_is_aac(int8_t* data, int size)
|
|
|
|
{
|
|
|
|
// 1bytes required.
|
|
|
|
if (size < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char sound_format = *(char*)data;
|
|
|
|
sound_format = (sound_format >> 4) & 0x0F;
|
|
|
|
|
2013-11-24 04:39:47 +00:00
|
|
|
return sound_format == SrsCodecAudioAAC;
|
2013-11-23 03:36:07 +00:00
|
|
|
}
|