winlin

fix #212, support publish aac adts raw stream. 2.0.31.

@@ -451,6 +451,10 @@ Supported operating systems and hardware: @@ -451,6 +451,10 @@ Supported operating systems and hardware:
451 1. Support compile [srs-librtmp on windows](https://github.com/winlinvip/srs.librtmp), 451 1. Support compile [srs-librtmp on windows](https://github.com/winlinvip/srs.librtmp),
452 [bug #213](https://github.com/winlinvip/simple-rtmp-server/issues/213). 452 [bug #213](https://github.com/winlinvip/simple-rtmp-server/issues/213).
453 1. Support [7.5k+ clients](https://github.com/winlinvip/simple-rtmp-server/issues/217), 4Gbps per process. 453 1. Support [7.5k+ clients](https://github.com/winlinvip/simple-rtmp-server/issues/217), 4Gbps per process.
  454 +1. Support publish aac adts raw stream(
  455 +[CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_SrsLibrtmp#publish-audio-raw-stream),
  456 +[EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_SrsLibrtmp#publish-audio-raw-stream)
  457 +) by srs-librtmp.
454 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech). 458 1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech).
455 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92). 459 1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92).
456 1. [no-plan] Support multiple processes, for both origin and edge 460 1. [no-plan] Support multiple processes, for both origin and edge
@@ -483,6 +487,7 @@ Supported operating systems and hardware: @@ -483,6 +487,7 @@ Supported operating systems and hardware:
483 * 2013-10-17, Created.<br/> 487 * 2013-10-17, Created.<br/>
484 488
485 ## History 489 ## History
  490 +* v2.0, 2014-11-24, fix [#212](https://github.com/winlinvip/simple-rtmp-server/issues/212), support publish aac adts raw stream. 2.0.31.
486 * v2.0, 2014-11-22, fix [#217](https://github.com/winlinvip/simple-rtmp-server/issues/217), remove timeout recv, support 7.5k+ 250kbps clients. 2.0.30. 491 * v2.0, 2014-11-22, fix [#217](https://github.com/winlinvip/simple-rtmp-server/issues/217), remove timeout recv, support 7.5k+ 250kbps clients. 2.0.30.
487 * v2.0, 2014-11-21, srs-librtmp add rtmp prefix for rtmp/utils/human apis. 2.0.29. 492 * v2.0, 2014-11-21, srs-librtmp add rtmp prefix for rtmp/utils/human apis. 2.0.29.
488 * v2.0, 2014-11-21, refine examples of srs-librtmp, add srs_print_rtmp_packet. 2.0.28. 493 * v2.0, 2014-11-21, refine examples of srs-librtmp, add srs_print_rtmp_packet. 2.0.28.
@@ -7,7 +7,7 @@ else @@ -7,7 +7,7 @@ else
7 objs/srs_flv_injecter objs/srs_publish objs/srs_play \ 7 objs/srs_flv_injecter objs/srs_publish objs/srs_play \
8 objs/srs_ingest_flv objs/srs_ingest_rtmp objs/srs_detect_rtmp \ 8 objs/srs_ingest_flv objs/srs_ingest_rtmp objs/srs_detect_rtmp \
9 objs/srs_bandwidth_check objs/srs_h264_raw_publish \ 9 objs/srs_bandwidth_check objs/srs_h264_raw_publish \
10 - objs/srs_audio_raw_publish 10 + objs/srs_audio_raw_publish objs/srs_aac_raw_publish
11 endif 11 endif
12 12
13 .PHONY: default clean help ssl nossl 13 .PHONY: default clean help ssl nossl
@@ -26,6 +26,7 @@ help: @@ -26,6 +26,7 @@ help:
26 @echo " srs_publish publish program using srs-librtmp" 26 @echo " srs_publish publish program using srs-librtmp"
27 @echo " srs_h264_raw_publish publish raw h.264 stream to SSR by srs-librtmp" 27 @echo " srs_h264_raw_publish publish raw h.264 stream to SSR by srs-librtmp"
28 @echo " srs_audio_raw_publish publish raw audio stream to SSR by srs-librtmp" 28 @echo " srs_audio_raw_publish publish raw audio stream to SSR by srs-librtmp"
  29 + @echo " srs_aac_raw_publish publish raw aac stream to SSR by srs-librtmp"
29 @echo " srs_play play program using srs-librtmp" 30 @echo " srs_play play program using srs-librtmp"
30 @echo " srs_ingest_flv ingest flv file and publish to RTMP server." 31 @echo " srs_ingest_flv ingest flv file and publish to RTMP server."
31 @echo " srs_ingest_rtmp ingest RTMP and publish to RTMP server." 32 @echo " srs_ingest_rtmp ingest RTMP and publish to RTMP server."
@@ -90,6 +91,9 @@ objs/srs_h264_raw_publish: srs_h264_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIB @@ -90,6 +91,9 @@ objs/srs_h264_raw_publish: srs_h264_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIB
90 objs/srs_audio_raw_publish: srs_audio_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) 91 objs/srs_audio_raw_publish: srs_audio_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
91 $(GCC) srs_audio_raw_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_audio_raw_publish 92 $(GCC) srs_audio_raw_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_audio_raw_publish
92 93
  94 +objs/srs_aac_raw_publish: srs_aac_raw_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
  95 + $(GCC) srs_aac_raw_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_aac_raw_publish
  96 +
93 objs/srs_play: srs_play.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) 97 objs/srs_play: srs_play.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
94 $(GCC) srs_play.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_play 98 $(GCC) srs_play.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_play
95 99
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +/**
  24 +gcc srs_aac_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_aac_raw_publish
  25 +*/
  26 +
  27 +#include <stdio.h>
  28 +#include <stdlib.h>
  29 +#include <unistd.h>
  30 +
  31 +// for open audio raw file.
  32 +#include <sys/types.h>
  33 +#include <sys/stat.h>
  34 +#include <fcntl.h>
  35 +
  36 +#include "../../objs/include/srs_librtmp.h"
  37 +
  38 +// https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-63648892
  39 +// allspace:
  40 +// Take this file as an example: https://github.com/allspace/files/blob/master/srs.pcm
  41 +// It's captured using SDK callback method. I have filtered out h264 video, so it's audio only now.
  42 +// For every frame, it's a 8 bytes vendor specific header, following 160 bytes audio frame.
  43 +// The header part can be ignored.
  44 +int read_audio_frame(char* data, int size, char** pp, char** frame, int* frame_size)
  45 +{
  46 + char* p = *pp;
  47 +
  48 + // @remark, for this demo, to publish aac raw file to SRS,
  49 + // we search the adts frame from the buffer which cached the aac data.
  50 + // please get aac adts raw data from device, it always a encoded frame.
  51 + if (!srs_aac_is_adts(p, size - (p - data))) {
  52 + srs_human_trace("aac adts raw data invalid.");
  53 + return -1;
  54 + }
  55 +
  56 + // @see srs_audio_write_raw_frame
  57 + // each frame prefixed aac adts header, '1111 1111 1111'B, that is 0xFFF.,
  58 + // for instance, frame = FF F1 5C 80 13 A0 FC 00 D0 33 83 E8 5B
  59 + *frame = p;
  60 + // skip some data.
  61 + // @remark, user donot need to do this.
  62 + p += srs_aac_adts_frame_size(p, size - (p - data));
  63 +
  64 + *pp = p;
  65 + *frame_size = p - *frame;
  66 + if (*frame_size <= 0) {
  67 + srs_human_trace("aac adts raw data invalid.");
  68 + return -1;
  69 + }
  70 +
  71 + return 0;
  72 +}
  73 +
  74 +int main(int argc, char** argv)
  75 +{
  76 + printf("publish raw audio as rtmp stream to server like FMLE/FFMPEG/Encoder\n");
  77 + printf("SRS(simple-rtmp-server) client librtmp library.\n");
  78 + printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision());
  79 +
  80 + if (argc <= 2) {
  81 + printf("Usage: %s <audio_raw_file> <rtmp_publish_url>\n", argv[0]);
  82 + printf(" audio_raw_file: the audio raw steam file.\n");
  83 + printf(" rtmp_publish_url: the rtmp publish url.\n");
  84 + printf("For example:\n");
  85 + printf(" %s ./audio.raw.aac rtmp://127.0.0.1:1935/live/livestream\n", argv[0]);
  86 + printf("Where the file: http://winlinvip.github.io/srs.release/3rdparty/audio.raw.aac\n");
  87 + printf("See: https://github.com/winlinvip/simple-rtmp-server/issues/212\n");
  88 + exit(-1);
  89 + }
  90 +
  91 + const char* raw_file = argv[1];
  92 + const char* rtmp_url = argv[2];
  93 + srs_human_trace("raw_file=%s, rtmp_url=%s", raw_file, rtmp_url);
  94 +
  95 + // open file
  96 + int raw_fd = open(raw_file, O_RDONLY);
  97 + if (raw_fd < 0) {
  98 + srs_human_trace("open audio raw file %s failed.", raw_fd);
  99 + goto rtmp_destroy;
  100 + }
  101 +
  102 + off_t file_size = lseek(raw_fd, 0, SEEK_END);
  103 + if (file_size <= 0) {
  104 + srs_human_trace("audio raw file %s empty.", raw_file);
  105 + goto rtmp_destroy;
  106 + }
  107 + srs_human_trace("read entirely audio raw file, size=%dKB", (int)(file_size / 1024));
  108 +
  109 + char* audio_raw = (char*)malloc(file_size);
  110 + if (!audio_raw) {
  111 + srs_human_trace("alloc raw buffer failed for file %s.", raw_file);
  112 + goto rtmp_destroy;
  113 + }
  114 +
  115 + lseek(raw_fd, 0, SEEK_SET);
  116 + ssize_t nb_read = 0;
  117 + if ((nb_read = read(raw_fd, audio_raw, file_size)) != file_size) {
  118 + srs_human_trace("buffer %s failed, expect=%dKB, actual=%dKB.",
  119 + raw_file, (int)(file_size / 1024), (int)(nb_read / 1024));
  120 + goto rtmp_destroy;
  121 + }
  122 +
  123 + // connect rtmp context
  124 + srs_rtmp_t rtmp = srs_rtmp_create(rtmp_url);
  125 +
  126 + if (srs_rtmp_handshake(rtmp) != 0) {
  127 + srs_human_trace("simple handshake failed.");
  128 + goto rtmp_destroy;
  129 + }
  130 + srs_human_trace("simple handshake success");
  131 +
  132 + if (srs_rtmp_connect_app(rtmp) != 0) {
  133 + srs_human_trace("connect vhost/app failed.");
  134 + goto rtmp_destroy;
  135 + }
  136 + srs_human_trace("connect vhost/app success");
  137 +
  138 + if (srs_rtmp_publish_stream(rtmp) != 0) {
  139 + srs_human_trace("publish stream failed.");
  140 + goto rtmp_destroy;
  141 + }
  142 + srs_human_trace("publish stream success");
  143 +
  144 + u_int32_t timestamp = 0;
  145 + u_int32_t time_delta = 45;
  146 + // @remark, to decode the file.
  147 + char* p = audio_raw;
  148 + for (;p < audio_raw + file_size;) {
  149 + // @remark, read a frame from file buffer.
  150 + char* data = NULL;
  151 + int size = 0;
  152 + if (read_audio_frame(audio_raw, file_size, &p, &data, &size) < 0) {
  153 + srs_human_trace("read a frame from file buffer failed.");
  154 + goto rtmp_destroy;
  155 + }
  156 +
  157 + // 0 = Linear PCM, platform endian
  158 + // 1 = ADPCM
  159 + // 2 = MP3
  160 + // 7 = G.711 A-law logarithmic PCM
  161 + // 8 = G.711 mu-law logarithmic PCM
  162 + // 10 = AAC
  163 + // 11 = Speex
  164 + char sound_format = 10;
  165 + // 2 = 22 kHz
  166 + char sound_rate = 2;
  167 + // 1 = 16-bit samples
  168 + char sound_size = 1;
  169 + // 1 = Stereo sound
  170 + char sound_type = 1;
  171 +
  172 + timestamp += time_delta;
  173 +
  174 + int ret = 0;
  175 + if ((ret = srs_audio_write_raw_frame(rtmp,
  176 + sound_format, sound_rate, sound_size, sound_type,
  177 + data, size, timestamp)) != 0
  178 + ) {
  179 + srs_human_trace("send audio raw data failed. ret=%d", ret);
  180 + goto rtmp_destroy;
  181 + }
  182 +
  183 + srs_human_trace("sent packet: type=%s, time=%d, size=%d, codec=%d, rate=%d, sample=%d, channel=%d",
  184 + srs_human_flv_tag_type2string(SRS_RTMP_TYPE_AUDIO), timestamp, size, sound_format, sound_rate, sound_size,
  185 + sound_type);
  186 +
  187 + // @remark, when use encode device, it not need to sleep.
  188 + usleep(1000 * time_delta);
  189 + }
  190 +
  191 +rtmp_destroy:
  192 + srs_rtmp_destroy(rtmp);
  193 + close(raw_fd);
  194 + free(audio_raw);
  195 +
  196 + return 0;
  197 +}
  198 +
@@ -166,7 +166,7 @@ int main(int argc, char** argv) @@ -166,7 +166,7 @@ int main(int argc, char** argv)
166 166
167 if (srs_audio_write_raw_frame(rtmp, 167 if (srs_audio_write_raw_frame(rtmp,
168 sound_format, sound_rate, sound_size, sound_type, 168 sound_format, sound_rate, sound_size, sound_type,
169 - 0, data, size, timestamp) != 0 169 + data, size, timestamp) != 0
170 ) { 170 ) {
171 srs_human_trace("send audio raw data failed."); 171 srs_human_trace("send audio raw data failed.");
172 goto rtmp_destroy; 172 goto rtmp_destroy;
@@ -166,16 +166,16 @@ int main(int argc, char** argv) @@ -166,16 +166,16 @@ int main(int argc, char** argv)
166 } 166 }
167 167
168 // send out the h264 packet over RTMP 168 // send out the h264 packet over RTMP
169 - int error = srs_h264_write_raw_frames(rtmp, data, size, dts, pts);  
170 - if (error != 0) {  
171 - if (srs_h264_is_dvbsp_error(error)) {  
172 - srs_human_trace("ignore drop video error, code=%d", error);  
173 - } else if (srs_h264_is_duplicated_sps_error(error)) {  
174 - srs_human_trace("ignore duplicated sps, code=%d", error);  
175 - } else if (srs_h264_is_duplicated_pps_error(error)) {  
176 - srs_human_trace("ignore duplicated pps, code=%d", error); 169 + int ret = srs_h264_write_raw_frames(rtmp, data, size, dts, pts);
  170 + if (ret != 0) {
  171 + if (srs_h264_is_dvbsp_error(ret)) {
  172 + srs_human_trace("ignore drop video error, code=%d", ret);
  173 + } else if (srs_h264_is_duplicated_sps_error(ret)) {
  174 + srs_human_trace("ignore duplicated sps, code=%d", ret);
  175 + } else if (srs_h264_is_duplicated_pps_error(ret)) {
  176 + srs_human_trace("ignore duplicated pps, code=%d", ret);
177 } else { 177 } else {
178 - srs_human_trace("send h264 raw data failed."); 178 + srs_human_trace("send h264 raw data failed. ret=%d", ret);
179 goto rtmp_destroy; 179 goto rtmp_destroy;
180 } 180 }
181 } 181 }
@@ -249,9 +249,6 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample @@ -249,9 +249,6 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample
249 return ret; 249 return ret;
250 } 250 }
251 251
252 - // aac_profile = audioObjectType - 1  
253 - aac_profile--;  
254 -  
255 // TODO: FIXME: to support aac he/he-v2, see: ngx_rtmp_codec_parse_aac_header 252 // TODO: FIXME: to support aac he/he-v2, see: ngx_rtmp_codec_parse_aac_header
256 // @see: https://github.com/winlinvip/nginx-rtmp-module/commit/3a5f9eea78fc8d11e8be922aea9ac349b9dcbfc2 253 // @see: https://github.com/winlinvip/nginx-rtmp-module/commit/3a5f9eea78fc8d11e8be922aea9ac349b9dcbfc2
257 // 254 //
@@ -39,25 +39,6 @@ class SrsAmf0Object; @@ -39,25 +39,6 @@ class SrsAmf0Object;
39 #define __SRS_AAC_SAMPLE_RATE_UNSET 15 39 #define __SRS_AAC_SAMPLE_RATE_UNSET 15
40 40
41 /** 41 /**
42 -* the FLV/RTMP supported audio sample rate.  
43 -* Sampling rate. The following values are defined:  
44 -* 0 = 5.5 kHz = 5512 Hz  
45 -* 1 = 11 kHz = 11025 Hz  
46 -* 2 = 22 kHz = 22050 Hz  
47 -* 3 = 44 kHz = 44100 Hz  
48 -*/  
49 -enum SrsCodecAudioSampleRate  
50 -{  
51 - // set to the max value to reserved, for array map.  
52 - SrsCodecAudioSampleRateReserved = 4,  
53 -  
54 - SrsCodecAudioSampleRate5512 = 0,  
55 - SrsCodecAudioSampleRate11025 = 1,  
56 - SrsCodecAudioSampleRate22050 = 2,  
57 - SrsCodecAudioSampleRate44100 = 3,  
58 -};  
59 -  
60 -/**  
61 * the FLV/RTMP supported audio sample size. 42 * the FLV/RTMP supported audio sample size.
62 * Size of each audio sample. This parameter only pertains to 43 * Size of each audio sample. This parameter only pertains to
63 * uncompressed formats. Compressed formats always decode 44 * uncompressed formats. Compressed formats always decode
@@ -224,8 +205,9 @@ public: @@ -224,8 +205,9 @@ public:
224 public: 205 public:
225 /** 206 /**
226 * audio specified 207 * audio specified
227 - * 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.  
228 - * audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40. 208 + * audioObjectType, in 1.6.2.1 AudioSpecificConfig, page 33,
  209 + * 1.5.1.1 Audio object type definition, page 23,
  210 + * in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf.
229 */ 211 */
230 u_int8_t aac_profile; 212 u_int8_t aac_profile;
231 /** 213 /**
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 30 34 +#define VERSION_REVISION 31
35 // server info. 35 // server info.
36 #define RTMP_SIG_SRS_KEY "SRS" 36 #define RTMP_SIG_SRS_KEY "SRS"
37 #define RTMP_SIG_SRS_ROLE "origin/edge server" 37 #define RTMP_SIG_SRS_ROLE "origin/edge server"
@@ -145,6 +145,25 @@ enum SrsCodecAudio @@ -145,6 +145,25 @@ enum SrsCodecAudio
145 }; 145 };
146 146
147 /** 147 /**
  148 +* the FLV/RTMP supported audio sample rate.
  149 +* Sampling rate. The following values are defined:
  150 +* 0 = 5.5 kHz = 5512 Hz
  151 +* 1 = 11 kHz = 11025 Hz
  152 +* 2 = 22 kHz = 22050 Hz
  153 +* 3 = 44 kHz = 44100 Hz
  154 +*/
  155 +enum SrsCodecAudioSampleRate
  156 +{
  157 + // set to the max value to reserved, for array map.
  158 + SrsCodecAudioSampleRateReserved = 4,
  159 +
  160 + SrsCodecAudioSampleRate5512 = 0,
  161 + SrsCodecAudioSampleRate11025 = 1,
  162 + SrsCodecAudioSampleRate22050 = 2,
  163 + SrsCodecAudioSampleRate44100 = 3,
  164 +};
  165 +
  166 +/**
148 * Annex E. The FLV File Format 167 * Annex E. The FLV File Format
149 * @see SrsAvcAacCodec for the media stream codec. 168 * @see SrsAvcAacCodec for the media stream codec.
150 */ 169 */
@@ -189,6 +189,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -189,6 +189,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
189 #define ERROR_H264_DROP_BEFORE_SPS_PPS 3043 189 #define ERROR_H264_DROP_BEFORE_SPS_PPS 3043
190 #define ERROR_H264_DUPLICATED_SPS 3044 190 #define ERROR_H264_DUPLICATED_SPS 3044
191 #define ERROR_H264_DUPLICATED_PPS 3045 191 #define ERROR_H264_DUPLICATED_PPS 3045
  192 +#define ERROR_AAC_REQUIRED_ADTS 3046
  193 +#define ERROR_AAC_ADTS_HEADER 3047
  194 +#define ERROR_AAC_DATA_INVALID 3048
192 195
193 /** 196 /**
194 * whether the error code is an system control error. 197 * whether the error code is an system control error.
@@ -75,7 +75,7 @@ struct Context @@ -75,7 +75,7 @@ struct Context
75 int stream_id; 75 int stream_id;
76 76
77 // for h264 raw stream, 77 // for h264 raw stream,
78 - // see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521 78 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521
79 SrsStream h264_raw_stream; 79 SrsStream h264_raw_stream;
80 // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62 80 // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62
81 std::string h264_sps; 81 std::string h264_sps;
@@ -87,6 +87,11 @@ struct Context @@ -87,6 +87,11 @@ struct Context
87 // @see https://github.com/winlinvip/simple-rtmp-server/issues/204 87 // @see https://github.com/winlinvip/simple-rtmp-server/issues/204
88 bool h264_sps_changed; 88 bool h264_sps_changed;
89 bool h264_pps_changed; 89 bool h264_pps_changed;
  90 + // for aac raw stream,
  91 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64146250
  92 + SrsStream aac_raw_stream;
  93 + // the aac sequence header.
  94 + std::string aac_specific_config;
90 95
91 Context() { 96 Context() {
92 rtmp = NULL; 97 rtmp = NULL;
@@ -859,22 +864,18 @@ int srs_rtmp_write_packet(srs_rtmp_t rtmp, char type, u_int32_t timestamp, char* @@ -859,22 +864,18 @@ int srs_rtmp_write_packet(srs_rtmp_t rtmp, char type, u_int32_t timestamp, char*
859 } 864 }
860 865
861 /** 866 /**
862 -* write audio raw frame to SRS. 867 +* directly write a audio frame.
863 */ 868 */
864 -int srs_audio_write_raw_frame(srs_rtmp_t rtmp, 869 +int __srs_write_audio_raw_frame(Context* context,
865 char sound_format, char sound_rate, char sound_size, char sound_type, 870 char sound_format, char sound_rate, char sound_size, char sound_type,
866 char aac_packet_type, char* frame, int frame_size, u_int32_t timestamp 871 char aac_packet_type, char* frame, int frame_size, u_int32_t timestamp
867 ) { 872 ) {
868 - Context* context = (Context*)rtmp;  
869 - srs_assert(context);  
870 -  
871 - // TODO: FIXME: for aac, must send the sequence header first.  
872 873
873 // for audio frame, there is 1 or 2 bytes header: 874 // for audio frame, there is 1 or 2 bytes header:
874 // 1bytes, SoundFormat|SoundRate|SoundSize|SoundType 875 // 1bytes, SoundFormat|SoundRate|SoundSize|SoundType
875 - // 1bytes, AACPacketType for SoundFormat == 10 876 + // 1bytes, AACPacketType for SoundFormat == 10, 0 is sequence header.
876 int size = frame_size + 1; 877 int size = frame_size + 1;
877 - if (aac_packet_type == SrsCodecAudioAAC) { 878 + if (sound_format == SrsCodecAudioAAC) {
878 size += 1; 879 size += 1;
879 } 880 }
880 char* data = new char[size]; 881 char* data = new char[size];
@@ -887,7 +888,7 @@ int srs_audio_write_raw_frame(srs_rtmp_t rtmp, @@ -887,7 +888,7 @@ int srs_audio_write_raw_frame(srs_rtmp_t rtmp,
887 888
888 *p++ = audio_header; 889 *p++ = audio_header;
889 890
890 - if (aac_packet_type == SrsCodecAudioAAC) { 891 + if (sound_format == SrsCodecAudioAAC) {
891 *p++ = aac_packet_type; 892 *p++ = aac_packet_type;
892 } 893 }
893 894
@@ -897,6 +898,278 @@ int srs_audio_write_raw_frame(srs_rtmp_t rtmp, @@ -897,6 +898,278 @@ int srs_audio_write_raw_frame(srs_rtmp_t rtmp,
897 } 898 }
898 899
899 /** 900 /**
  901 +* write aac frame in adts.
  902 +*/
  903 +int __srs_write_aac_adts_frame(Context* context,
  904 + char sound_format, char sound_rate, char sound_size, char sound_type,
  905 + char aac_profile, char aac_samplerate, char aac_channel,
  906 + char* frame, int frame_size, u_int32_t timestamp
  907 +) {
  908 + int ret = ERROR_SUCCESS;
  909 +
  910 + // override the aac samplerate by user specified.
  911 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64146899
  912 + switch (sound_rate) {
  913 + case SrsCodecAudioSampleRate11025:
  914 + aac_samplerate = 0x0a; break;
  915 + case SrsCodecAudioSampleRate22050:
  916 + aac_samplerate = 0x07; break;
  917 + case SrsCodecAudioSampleRate44100:
  918 + aac_samplerate = 0x04; break;
  919 + default:
  920 + break;
  921 + }
  922 +
  923 + // send out aac sequence header if not sent.
  924 + if (context->aac_specific_config.empty()) {
  925 + char ch = 0;
  926 + // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf
  927 + // AudioSpecificConfig (), page 33
  928 + // 1.6.2.1 AudioSpecificConfig
  929 + // audioObjectType; 5 bslbf
  930 + ch = (aac_profile << 3) & 0xf8;
  931 + // 3bits left.
  932 +
  933 + // samplingFrequencyIndex; 4 bslbf
  934 + ch |= (aac_samplerate >> 1) & 0x07;
  935 + context->aac_specific_config += ch;
  936 + ch = (aac_samplerate << 7) & 0x80;
  937 + if (aac_samplerate == 0x0f) {
  938 + return ERROR_AAC_DATA_INVALID;
  939 + }
  940 + // 7bits left.
  941 +
  942 + // channelConfiguration; 4 bslbf
  943 + ch |= (aac_channel << 3) & 0x70;
  944 + // 3bits left.
  945 +
  946 + // only support aac profile 1-4.
  947 + if (aac_profile < 1 || aac_profile > 4) {
  948 + return ERROR_AAC_DATA_INVALID;
  949 + }
  950 + // GASpecificConfig(), page 451
  951 + // 4.4.1 Decoder configuration (GASpecificConfig)
  952 + // frameLengthFlag; 1 bslbf
  953 + // dependsOnCoreCoder; 1 bslbf
  954 + // extensionFlag; 1 bslbf
  955 + context->aac_specific_config += ch;
  956 +
  957 + if ((ret = __srs_write_audio_raw_frame(context,
  958 + sound_format, sound_rate, sound_size, sound_type,
  959 + 0, (char*)context->aac_specific_config.data(),
  960 + context->aac_specific_config.length(),
  961 + timestamp)) != ERROR_SUCCESS
  962 + ) {
  963 + return ret;
  964 + }
  965 + }
  966 +
  967 + return __srs_write_audio_raw_frame(context,
  968 + sound_format, sound_rate, sound_size, sound_type,
  969 + 1, frame, frame_size, timestamp);
  970 +}
  971 +
  972 +/**
  973 +* write aac frames in adts.
  974 +*/
  975 +int __srs_write_aac_adts_frames(Context* context,
  976 + char sound_format, char sound_rate, char sound_size, char sound_type,
  977 + char* frame, int frame_size, u_int32_t timestamp
  978 +) {
  979 + int ret = ERROR_SUCCESS;
  980 +
  981 + SrsStream* stream = &context->aac_raw_stream;
  982 + if ((ret = stream->initialize(frame, frame_size)) != ERROR_SUCCESS) {
  983 + return ret;
  984 + }
  985 +
  986 + while (!stream->empty()) {
  987 + int adts_header_start = stream->pos();
  988 +
  989 + // decode the ADTS.
  990 + // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75,
  991 + // 1.A.2.2 Audio_Data_Transport_Stream frame, ADTS
  992 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64145885
  993 + // byte_alignment()
  994 +
  995 + // adts_fixed_header:
  996 + // 12bits syncword,
  997 + // 16bits left.
  998 + // adts_variable_header:
  999 + // 28bits
  1000 + // 12+16+28=56bits
  1001 + // adts_error_check:
  1002 + // 16bits if protection_absent
  1003 + // 56+16=72bits
  1004 + // if protection_absent:
  1005 + // require(7bytes)=56bits
  1006 + // else
  1007 + // require(9bytes)=72bits
  1008 + if (!stream->require(7)) {
  1009 + return ERROR_AAC_ADTS_HEADER;
  1010 + }
  1011 +
  1012 + // for aac, the frame must be ADTS format.
  1013 + if (!srs_aac_startswith_adts(stream)) {
  1014 + return ERROR_AAC_REQUIRED_ADTS;
  1015 + }
  1016 +
  1017 + // Syncword 12 bslbf
  1018 + stream->read_1bytes();
  1019 + // 4bits left.
  1020 + // adts_fixed_header(), 1.A.2.2.1 Fixed Header of ADTS
  1021 + // ID 1 bslbf
  1022 + // Layer 2 uimsbf
  1023 + // protection_absent 1 bslbf
  1024 + int8_t fh0 = (stream->read_1bytes() & 0x0f);
  1025 + /*int8_t fh_id = (fh0 >> 3) & 0x01;*/
  1026 + /*int8_t fh_layer = (fh0 >> 1) & 0x03;*/
  1027 + int8_t fh_protection_absent = fh0 & 0x01;
  1028 +
  1029 + int16_t fh1 = stream->read_2bytes();
  1030 + // Profile_ObjectType 2 uimsbf
  1031 + // sampling_frequency_index 4 uimsbf
  1032 + // private_bit 1 bslbf
  1033 + // channel_configuration 3 uimsbf
  1034 + // original/copy 1 bslbf
  1035 + // home 1 bslbf
  1036 + int8_t fh_Profile_ObjectType = (fh1 >> 14) & 0x03;
  1037 + int8_t fh_sampling_frequency_index = (fh1 >> 10) & 0x0f;
  1038 + /*int8_t fh_private_bit = (fh1 >> 9) & 0x01;*/
  1039 + int8_t fh_channel_configuration = (fh1 >> 6) & 0x07;
  1040 + /*int8_t fh_original = (fh1 >> 5) & 0x01;*/
  1041 + /*int8_t fh_home = (fh1 >> 4) & 0x01;*/
  1042 + // @remark, Emphasis is removed,
  1043 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736
  1044 + //int8_t fh_Emphasis = (fh1 >> 2) & 0x03;
  1045 + // 4bits left.
  1046 + // adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
  1047 + // copyright_identification_bit 1 bslbf
  1048 + // copyright_identification_start 1 bslbf
  1049 + /*int8_t fh_copyright_identification_bit = (fh1 >> 3) & 0x01;*/
  1050 + /*int8_t fh_copyright_identification_start = (fh1 >> 2) & 0x01;*/
  1051 + // aac_frame_length 13 bslbf: Length of the frame including headers and error_check in bytes.
  1052 + // use the left 2bits as the 13 and 12 bit,
  1053 + // the aac_frame_length is 13bits, so we move 13-2=11.
  1054 + int16_t fh_aac_frame_length = (fh1 << 11) & 0x0800;
  1055 +
  1056 + int32_t fh2 = stream->read_3bytes();
  1057 + // aac_frame_length 13 bslbf: consume the first 13-2=11bits
  1058 + // the fh2 is 24bits, so we move right 24-11=13.
  1059 + fh_aac_frame_length |= (fh2 >> 13) & 0x07ff;
  1060 + // adts_buffer_fullness 11 bslbf
  1061 + /*int16_t fh_adts_buffer_fullness = (fh2 >> 2) & 0x7ff;*/
  1062 + // no_raw_data_blocks_in_frame 2 uimsbf
  1063 + /*int16_t fh_no_raw_data_blocks_in_frame = fh2 & 0x03;*/
  1064 + // adts_error_check(), 1.A.2.2.3 Error detection
  1065 + if (!fh_protection_absent) {
  1066 + if (!stream->require(2)) {
  1067 + return ERROR_AAC_ADTS_HEADER;
  1068 + }
  1069 + // crc_check 16 Rpchof
  1070 + /*int16_t crc_check = */stream->read_2bytes();
  1071 + }
  1072 +
  1073 + // TODO: check the fh_sampling_frequency_index
  1074 + // TODO: check the fh_channel_configuration
  1075 +
  1076 + // raw_data_blocks
  1077 + int adts_header_size = stream->pos() - adts_header_start;
  1078 + int raw_data_size = fh_aac_frame_length - adts_header_size;
  1079 + if (!stream->require(raw_data_size)) {
  1080 + return ERROR_AAC_ADTS_HEADER;
  1081 + }
  1082 +
  1083 + char* raw_data = stream->data() + stream->pos();
  1084 + if ((ret = __srs_write_aac_adts_frame(context,
  1085 + sound_format, sound_rate, sound_size, sound_type,
  1086 + fh_Profile_ObjectType, fh_sampling_frequency_index, fh_channel_configuration,
  1087 + raw_data, raw_data_size, timestamp)) != ERROR_SUCCESS
  1088 + ) {
  1089 + return ret;
  1090 + }
  1091 + stream->skip(raw_data_size);
  1092 + }
  1093 +
  1094 + return ret;
  1095 +}
  1096 +
  1097 +/**
  1098 +* write audio raw frame to SRS.
  1099 +*/
  1100 +int srs_audio_write_raw_frame(srs_rtmp_t rtmp,
  1101 + char sound_format, char sound_rate, char sound_size, char sound_type,
  1102 + char* frame, int frame_size, u_int32_t timestamp
  1103 +) {
  1104 + int ret = ERROR_SUCCESS;
  1105 +
  1106 + Context* context = (Context*)rtmp;
  1107 + srs_assert(context);
  1108 +
  1109 + if (sound_format == SrsCodecAudioAAC) {
  1110 + // for aac, the frame must be ADTS format.
  1111 + if (!srs_aac_is_adts(frame, frame_size)) {
  1112 + return ERROR_AAC_REQUIRED_ADTS;
  1113 + }
  1114 +
  1115 + // for aac, demux the ADTS to RTMP format.
  1116 + return __srs_write_aac_adts_frames(context,
  1117 + sound_format, sound_rate, sound_size, sound_type,
  1118 + frame, frame_size, timestamp);
  1119 + } else {
  1120 + // for other data, directly write frame.
  1121 + return __srs_write_audio_raw_frame(context,
  1122 + sound_format, sound_rate, sound_size, sound_type,
  1123 + 0, frame, frame_size, timestamp);
  1124 + }
  1125 +
  1126 +
  1127 + return ret;
  1128 +}
  1129 +
  1130 +/**
  1131 +* whether aac raw data is in adts format,
  1132 +* which bytes sequence matches '1111 1111 1111'B, that is 0xFFF.
  1133 +*/
  1134 +srs_bool srs_aac_is_adts(char* aac_raw_data, int ac_raw_size)
  1135 +{
  1136 + SrsStream stream;
  1137 + if (stream.initialize(aac_raw_data, ac_raw_size) != ERROR_SUCCESS) {
  1138 + return false;
  1139 + }
  1140 +
  1141 + return srs_aac_startswith_adts(&stream);
  1142 +}
  1143 +
  1144 +/**
  1145 +* parse the adts header to get the frame size.
  1146 +*/
  1147 +int srs_aac_adts_frame_size(char* aac_raw_data, int ac_raw_size)
  1148 +{
  1149 + int size = -1;
  1150 +
  1151 + if (!srs_aac_is_adts(aac_raw_data, ac_raw_size)) {
  1152 + return size;
  1153 + }
  1154 +
  1155 + // adts always 7bytes.
  1156 + if (ac_raw_size <= 7) {
  1157 + return size;
  1158 + }
  1159 +
  1160 + // last 2bits
  1161 + int16_t ch3 = aac_raw_data[3];
  1162 + // whole 8bits
  1163 + int16_t ch4 = aac_raw_data[4];
  1164 + // first 3bits
  1165 + int16_t ch5 = aac_raw_data[5];
  1166 +
  1167 + size = ((ch3 << 11) & 0x1800) | ((ch4 << 3) & 0x07f8) | ((ch5 >> 5) & 0x0007);
  1168 +
  1169 + return size;
  1170 +}
  1171 +
  1172 +/**
900 * write h264 packet, with rtmp header. 1173 * write h264 packet, with rtmp header.
901 * @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame. 1174 * @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame.
902 * @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU. 1175 * @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU.
@@ -1224,22 +1497,22 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -1224,22 +1497,22 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
1224 return error_code_return; 1497 return error_code_return;
1225 } 1498 }
1226 1499
1227 -srs_h264_bool srs_h264_is_dvbsp_error(int error_code) 1500 +srs_bool srs_h264_is_dvbsp_error(int error_code)
1228 { 1501 {
1229 return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS; 1502 return error_code == ERROR_H264_DROP_BEFORE_SPS_PPS;
1230 } 1503 }
1231 1504
1232 -srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code) 1505 +srs_bool srs_h264_is_duplicated_sps_error(int error_code)
1233 { 1506 {
1234 return error_code == ERROR_H264_DUPLICATED_SPS; 1507 return error_code == ERROR_H264_DUPLICATED_SPS;
1235 } 1508 }
1236 1509
1237 -srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code) 1510 +srs_bool srs_h264_is_duplicated_pps_error(int error_code)
1238 { 1511 {
1239 return error_code == ERROR_H264_DUPLICATED_PPS; 1512 return error_code == ERROR_H264_DUPLICATED_PPS;
1240 } 1513 }
1241 1514
1242 -int srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code) 1515 +srs_bool srs_h264_startswith_annexb(char* h264_raw_data, int h264_raw_size, int* pnb_start_code)
1243 { 1516 {
1244 SrsStream stream; 1517 SrsStream stream;
1245 if (stream.initialize(h264_raw_data, h264_raw_size) != ERROR_SUCCESS) { 1518 if (stream.initialize(h264_raw_data, h264_raw_size) != ERROR_SUCCESS) {
@@ -1417,17 +1690,17 @@ void srs_flv_lseek(srs_flv_t flv, int64_t offset) @@ -1417,17 +1690,17 @@ void srs_flv_lseek(srs_flv_t flv, int64_t offset)
1417 context->reader.lseek(offset); 1690 context->reader.lseek(offset);
1418 } 1691 }
1419 1692
1420 -srs_flv_bool srs_flv_is_eof(int error_code) 1693 +srs_bool srs_flv_is_eof(int error_code)
1421 { 1694 {
1422 return error_code == ERROR_SYSTEM_FILE_EOF; 1695 return error_code == ERROR_SYSTEM_FILE_EOF;
1423 } 1696 }
1424 1697
1425 -srs_flv_bool srs_flv_is_sequence_header(char* data, int32_t size) 1698 +srs_bool srs_flv_is_sequence_header(char* data, int32_t size)
1426 { 1699 {
1427 return SrsFlvCodec::video_is_sequence_header(data, (int)size); 1700 return SrsFlvCodec::video_is_sequence_header(data, (int)size);
1428 } 1701 }
1429 1702
1430 -srs_flv_bool srs_flv_is_keyframe(char* data, int32_t size) 1703 +srs_bool srs_flv_is_keyframe(char* data, int32_t size)
1431 { 1704 {
1432 return SrsFlvCodec::video_is_keyframe(data, (int)size); 1705 return SrsFlvCodec::video_is_keyframe(data, (int)size);
1433 } 1706 }
@@ -1517,43 +1790,43 @@ int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size) @@ -1517,43 +1790,43 @@ int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size)
1517 return ret; 1790 return ret;
1518 } 1791 }
1519 1792
1520 -srs_amf0_bool srs_amf0_is_string(srs_amf0_t amf0) 1793 +srs_bool srs_amf0_is_string(srs_amf0_t amf0)
1521 { 1794 {
1522 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1795 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1523 return any->is_string(); 1796 return any->is_string();
1524 } 1797 }
1525 1798
1526 -srs_amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0) 1799 +srs_bool srs_amf0_is_boolean(srs_amf0_t amf0)
1527 { 1800 {
1528 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1801 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1529 return any->is_boolean(); 1802 return any->is_boolean();
1530 } 1803 }
1531 1804
1532 -srs_amf0_bool srs_amf0_is_number(srs_amf0_t amf0) 1805 +srs_bool srs_amf0_is_number(srs_amf0_t amf0)
1533 { 1806 {
1534 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1807 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1535 return any->is_number(); 1808 return any->is_number();
1536 } 1809 }
1537 1810
1538 -srs_amf0_bool srs_amf0_is_null(srs_amf0_t amf0) 1811 +srs_bool srs_amf0_is_null(srs_amf0_t amf0)
1539 { 1812 {
1540 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1813 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1541 return any->is_null(); 1814 return any->is_null();
1542 } 1815 }
1543 1816
1544 -srs_amf0_bool srs_amf0_is_object(srs_amf0_t amf0) 1817 +srs_bool srs_amf0_is_object(srs_amf0_t amf0)
1545 { 1818 {
1546 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1819 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1547 return any->is_object(); 1820 return any->is_object();
1548 } 1821 }
1549 1822
1550 -srs_amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0) 1823 +srs_bool srs_amf0_is_ecma_array(srs_amf0_t amf0)
1551 { 1824 {
1552 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1825 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1553 return any->is_ecma_array(); 1826 return any->is_ecma_array();
1554 } 1827 }
1555 1828
1556 -srs_amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0) 1829 +srs_bool srs_amf0_is_strict_array(srs_amf0_t amf0)
1557 { 1830 {
1558 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1831 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1559 return any->is_strict_array(); 1832 return any->is_strict_array();
@@ -1565,7 +1838,7 @@ const char* srs_amf0_to_string(srs_amf0_t amf0) @@ -1565,7 +1838,7 @@ const char* srs_amf0_to_string(srs_amf0_t amf0)
1565 return any->to_str_raw(); 1838 return any->to_str_raw();
1566 } 1839 }
1567 1840
1568 -srs_amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0) 1841 +srs_bool srs_amf0_to_boolean(srs_amf0_t amf0)
1569 { 1842 {
1570 SrsAmf0Any* any = (SrsAmf0Any*)amf0; 1843 SrsAmf0Any* any = (SrsAmf0Any*)amf0;
1571 return any->to_boolean(); 1844 return any->to_boolean();
@@ -84,6 +84,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -84,6 +84,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
84 extern "C"{ 84 extern "C"{
85 #endif 85 #endif
86 86
  87 +// typedefs
  88 +typedef int srs_bool;
  89 +
87 /************************************************************* 90 /*************************************************************
88 ************************************************************** 91 **************************************************************
89 * srs-librtmp version 92 * srs-librtmp version
@@ -303,12 +306,15 @@ extern int srs_rtmp_write_packet(srs_rtmp_t rtmp, @@ -303,12 +306,15 @@ extern int srs_rtmp_write_packet(srs_rtmp_t rtmp,
303 * @param sound_type Mono or stereo sound 306 * @param sound_type Mono or stereo sound
304 * 0 = Mono sound 307 * 0 = Mono sound
305 * 1 = Stereo sound 308 * 1 = Stereo sound
306 -* @param aac_packet_type The following values are defined:  
307 -* 0 = AAC sequence header  
308 -* 1 = AAC raw  
309 * @param timestamp The timestamp of audio. 309 * @param timestamp The timestamp of audio.
310 * 310 *
311 -* @remark Ignore aac_packet_type if not aac(sound_format!=10). 311 +* @example /trunk/research/librtmp/srs_aac_raw_publish.c
  312 +* @example /trunk/research/librtmp/srs_audio_raw_publish.c
  313 +*
  314 +* @remark for aac, the frame must be in ADTS format.
  315 +* @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS
  316 +* @remark for aac, only support profile 1-4, AAC main/LC/SSR/LTP,
  317 +* @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 23, 1.5.1.1 Audio object type
312 * 318 *
313 * @see https://github.com/winlinvip/simple-rtmp-server/issues/212 319 * @see https://github.com/winlinvip/simple-rtmp-server/issues/212
314 * @see E.4.2.1 AUDIODATA of video_file_format_spec_v10_1.pdf 320 * @see E.4.2.1 AUDIODATA of video_file_format_spec_v10_1.pdf
@@ -317,15 +323,38 @@ extern int srs_rtmp_write_packet(srs_rtmp_t rtmp, @@ -317,15 +323,38 @@ extern int srs_rtmp_write_packet(srs_rtmp_t rtmp,
317 */ 323 */
318 extern int srs_audio_write_raw_frame(srs_rtmp_t rtmp, 324 extern int srs_audio_write_raw_frame(srs_rtmp_t rtmp,
319 char sound_format, char sound_rate, char sound_size, char sound_type, 325 char sound_format, char sound_rate, char sound_size, char sound_type,
320 - char aac_packet_type, char* frame, int frame_size, u_int32_t timestamp 326 + char* frame, int frame_size, u_int32_t timestamp
321 ); 327 );
322 328
  329 +/**
  330 +* whether aac raw data is in adts format,
  331 +* which bytes sequence matches '1111 1111 1111'B, that is 0xFFF.
  332 +* @param aac_raw_data the input aac raw data, a encoded aac frame data.
  333 +* @param ac_raw_size the size of aac raw data.
  334 +*
  335 +* @reamrk used to check whether current frame is in adts format.
  336 +* @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS
  337 +* @example /trunk/research/librtmp/srs_aac_raw_publish.c
  338 +*
  339 +* @return 0 false; otherwise, true.
  340 +*/
  341 +extern srs_bool srs_aac_is_adts(char* aac_raw_data, int ac_raw_size);
  342 +
  343 +/**
  344 +* parse the adts header to get the frame size,
  345 +* which bytes sequence matches '1111 1111 1111'B, that is 0xFFF.
  346 +* @param aac_raw_data the input aac raw data, a encoded aac frame data.
  347 +* @param ac_raw_size the size of aac raw data.
  348 +*
  349 +* @return failed when <=0 failed; otherwise, ok.
  350 +*/
  351 +extern int srs_aac_adts_frame_size(char* aac_raw_data, int ac_raw_size);
  352 +
323 /************************************************************* 353 /*************************************************************
324 ************************************************************** 354 **************************************************************
325 * h264 raw codec 355 * h264 raw codec
326 ************************************************************** 356 **************************************************************
327 *************************************************************/ 357 *************************************************************/
328 -typedef int srs_h264_bool;  
329 /** 358 /**
330 * write h.264 raw frame over RTMP to rtmp server. 359 * write h.264 raw frame over RTMP to rtmp server.
331 * @param frames the input h264 raw data, encoded h.264 I/P/B frames data. 360 * @param frames the input h264 raw data, encoded h.264 I/P/B frames data.
@@ -392,21 +421,21 @@ extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -392,21 +421,21 @@ extern int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
392 * so, when error and reconnect the rtmp, the first video is not sps/pps(sequence header), 421 * so, when error and reconnect the rtmp, the first video is not sps/pps(sequence header),
393 * this will cause SRS server to disable HLS. 422 * this will cause SRS server to disable HLS.
394 */ 423 */
395 -extern srs_h264_bool srs_h264_is_dvbsp_error(int error_code); 424 +extern srs_bool srs_h264_is_dvbsp_error(int error_code);
396 /** 425 /**
397 * whether error_code is duplicated sps error. 426 * whether error_code is duplicated sps error.
398 * 427 *
399 * @see https://github.com/winlinvip/simple-rtmp-server/issues/204 428 * @see https://github.com/winlinvip/simple-rtmp-server/issues/204
400 * @example /trunk/research/librtmp/srs_h264_raw_publish.c 429 * @example /trunk/research/librtmp/srs_h264_raw_publish.c
401 */ 430 */
402 -extern srs_h264_bool srs_h264_is_duplicated_sps_error(int error_code); 431 +extern srs_bool srs_h264_is_duplicated_sps_error(int error_code);
403 /** 432 /**
404 * whether error_code is duplicated pps error. 433 * whether error_code is duplicated pps error.
405 * 434 *
406 * @see https://github.com/winlinvip/simple-rtmp-server/issues/204 435 * @see https://github.com/winlinvip/simple-rtmp-server/issues/204
407 * @example /trunk/research/librtmp/srs_h264_raw_publish.c 436 * @example /trunk/research/librtmp/srs_h264_raw_publish.c
408 */ 437 */
409 -extern srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code); 438 +extern srs_bool srs_h264_is_duplicated_pps_error(int error_code);
410 /** 439 /**
411 * whether h264 raw data starts with the annexb, 440 * whether h264 raw data starts with the annexb,
412 * which bytes sequence matches N[00] 00 00 01, where N>=0. 441 * which bytes sequence matches N[00] 00 00 01, where N>=0.
@@ -420,7 +449,7 @@ extern srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code); @@ -420,7 +449,7 @@ extern srs_h264_bool srs_h264_is_duplicated_pps_error(int error_code);
420 * 449 *
421 * @return 0 false; otherwise, true. 450 * @return 0 false; otherwise, true.
422 */ 451 */
423 -extern int srs_h264_startswith_annexb( 452 +extern srs_bool srs_h264_startswith_annexb(
424 char* h264_raw_data, int h264_raw_size, 453 char* h264_raw_data, int h264_raw_size,
425 int* pnb_start_code 454 int* pnb_start_code
426 ); 455 );
@@ -435,7 +464,6 @@ extern int srs_h264_startswith_annexb( @@ -435,7 +464,6 @@ extern int srs_h264_startswith_annexb(
435 ************************************************************** 464 **************************************************************
436 *************************************************************/ 465 *************************************************************/
437 typedef void* srs_flv_t; 466 typedef void* srs_flv_t;
438 -typedef int srs_flv_bool;  
439 /* open flv file for both read/write. */ 467 /* open flv file for both read/write. */
440 extern srs_flv_t srs_flv_open_read(const char* file); 468 extern srs_flv_t srs_flv_open_read(const char* file);
441 extern srs_flv_t srs_flv_open_write(const char* file); 469 extern srs_flv_t srs_flv_open_write(const char* file);
@@ -510,20 +538,20 @@ extern int64_t srs_flv_tellg(srs_flv_t flv); @@ -510,20 +538,20 @@ extern int64_t srs_flv_tellg(srs_flv_t flv);
510 extern void srs_flv_lseek(srs_flv_t flv, int64_t offset); 538 extern void srs_flv_lseek(srs_flv_t flv, int64_t offset);
511 /* error code */ 539 /* error code */
512 /* whether the error code indicates EOF */ 540 /* whether the error code indicates EOF */
513 -extern srs_flv_bool srs_flv_is_eof(int error_code); 541 +extern srs_bool srs_flv_is_eof(int error_code);
514 /* media codec */ 542 /* media codec */
515 /** 543 /**
516 * whether the video body is sequence header 544 * whether the video body is sequence header
517 * @param data, the data of tag, read by srs_flv_read_tag_data(). 545 * @param data, the data of tag, read by srs_flv_read_tag_data().
518 * @param size, the size of tag, read by srs_flv_read_tag_data(). 546 * @param size, the size of tag, read by srs_flv_read_tag_data().
519 */ 547 */
520 -extern srs_flv_bool srs_flv_is_sequence_header(char* data, int32_t size); 548 +extern srs_bool srs_flv_is_sequence_header(char* data, int32_t size);
521 /** 549 /**
522 * whether the video body is keyframe 550 * whether the video body is keyframe
523 * @param data, the data of tag, read by srs_flv_read_tag_data(). 551 * @param data, the data of tag, read by srs_flv_read_tag_data().
524 * @param size, the size of tag, read by srs_flv_read_tag_data(). 552 * @param size, the size of tag, read by srs_flv_read_tag_data().
525 */ 553 */
526 -extern srs_flv_bool srs_flv_is_keyframe(char* data, int32_t size); 554 +extern srs_bool srs_flv_is_keyframe(char* data, int32_t size);
527 555
528 /************************************************************* 556 /*************************************************************
529 ************************************************************** 557 **************************************************************
@@ -534,7 +562,6 @@ extern srs_flv_bool srs_flv_is_keyframe(char* data, int32_t size); @@ -534,7 +562,6 @@ extern srs_flv_bool srs_flv_is_keyframe(char* data, int32_t size);
534 *************************************************************/ 562 *************************************************************/
535 /* the output handler. */ 563 /* the output handler. */
536 typedef void* srs_amf0_t; 564 typedef void* srs_amf0_t;
537 -typedef int srs_amf0_bool;  
538 typedef double srs_amf0_number; 565 typedef double srs_amf0_number;
539 /** 566 /**
540 * parse amf0 from data. 567 * parse amf0 from data.
@@ -552,16 +579,16 @@ extern void srs_amf0_free_bytes(char* data); @@ -552,16 +579,16 @@ extern void srs_amf0_free_bytes(char* data);
552 extern int srs_amf0_size(srs_amf0_t amf0); 579 extern int srs_amf0_size(srs_amf0_t amf0);
553 extern int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size); 580 extern int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size);
554 /* type detecter */ 581 /* type detecter */
555 -extern srs_amf0_bool srs_amf0_is_string(srs_amf0_t amf0);  
556 -extern srs_amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0);  
557 -extern srs_amf0_bool srs_amf0_is_number(srs_amf0_t amf0);  
558 -extern srs_amf0_bool srs_amf0_is_null(srs_amf0_t amf0);  
559 -extern srs_amf0_bool srs_amf0_is_object(srs_amf0_t amf0);  
560 -extern srs_amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0);  
561 -extern srs_amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0); 582 +extern srs_bool srs_amf0_is_string(srs_amf0_t amf0);
  583 +extern srs_bool srs_amf0_is_boolean(srs_amf0_t amf0);
  584 +extern srs_bool srs_amf0_is_number(srs_amf0_t amf0);
  585 +extern srs_bool srs_amf0_is_null(srs_amf0_t amf0);
  586 +extern srs_bool srs_amf0_is_object(srs_amf0_t amf0);
  587 +extern srs_bool srs_amf0_is_ecma_array(srs_amf0_t amf0);
  588 +extern srs_bool srs_amf0_is_strict_array(srs_amf0_t amf0);
562 /* value converter */ 589 /* value converter */
563 extern const char* srs_amf0_to_string(srs_amf0_t amf0); 590 extern const char* srs_amf0_to_string(srs_amf0_t amf0);
564 -extern srs_amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0); 591 +extern srs_bool srs_amf0_to_boolean(srs_amf0_t amf0);
565 extern srs_amf0_number srs_amf0_to_number(srs_amf0_t amf0); 592 extern srs_amf0_number srs_amf0_to_number(srs_amf0_t amf0);
566 /* value setter */ 593 /* value setter */
567 extern void srs_amf0_set_number(srs_amf0_t amf0, srs_amf0_number value); 594 extern void srs_amf0_set_number(srs_amf0_t amf0, srs_amf0_number value);
@@ -167,12 +167,12 @@ bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) @@ -167,12 +167,12 @@ bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code)
167 } 167 }
168 168
169 // not match 169 // not match
170 - if (p[0] != 0x00 || p[1] != 0x00) { 170 + if (p[0] != (char)0x00 || p[1] != (char)0x00) {
171 return false; 171 return false;
172 } 172 }
173 173
174 // match N[00] 00 00 01, where N>=0 174 // match N[00] 00 00 01, where N>=0
175 - if (p[2] == 0x01) { 175 + if (p[2] == (char)0x01) {
176 if (pnb_start_code) { 176 if (pnb_start_code) {
177 *pnb_start_code = (int)(p - bytes) + 3; 177 *pnb_start_code = (int)(p - bytes) + 3;
178 } 178 }
@@ -185,3 +185,21 @@ bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code) @@ -185,3 +185,21 @@ bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code)
185 return false; 185 return false;
186 } 186 }
187 187
  188 +bool srs_aac_startswith_adts(SrsStream* stream)
  189 +{
  190 + char* bytes = stream->data() + stream->pos();
  191 + char* p = bytes;
  192 +
  193 + if (!stream->require(p - bytes + 2)) {
  194 + return false;
  195 + }
  196 +
  197 + // matched 12bits 0xFFF,
  198 + // @remark, we must cast the 0xff to char to compare.
  199 + if (p[0] != (char)0xff || (char)(p[1] & 0xf0) != (char)0xf0) {
  200 + return false;
  201 + }
  202 +
  203 + return true;
  204 +}
  205 +
@@ -96,5 +96,12 @@ extern bool srs_bytes_equals(void* pa, void* pb, int size); @@ -96,5 +96,12 @@ extern bool srs_bytes_equals(void* pa, void* pb, int size);
96 */ 96 */
97 extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL); 97 extern bool srs_avc_startswith_annexb(SrsStream* stream, int* pnb_start_code = NULL);
98 98
  99 +/**
  100 +* whether stream starts with the aac ADTS
  101 +* from aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS.
  102 +* start code must be '1111 1111 1111'B, that is 0xFFF
  103 +*/
  104 +extern bool srs_aac_startswith_adts(SrsStream* stream);
  105 +
99 #endif 106 #endif
100 107
@@ -130,6 +130,7 @@ file @@ -130,6 +130,7 @@ file
130 ..\utest\srs_utest_reload.hpp, 130 ..\utest\srs_utest_reload.hpp,
131 ..\utest\srs_utest_reload.cpp, 131 ..\utest\srs_utest_reload.cpp,
132 research readonly separator, 132 research readonly separator,
  133 + ..\..\research\librtmp\srs_aac_raw_publish.c,
133 ..\..\research\librtmp\srs_audio_raw_publish.c, 134 ..\..\research\librtmp\srs_audio_raw_publish.c,
134 ..\..\research\librtmp\srs_bandwidth_check.c, 135 ..\..\research\librtmp\srs_bandwidth_check.c,
135 ..\..\research\librtmp\srs_detect_rtmp.c, 136 ..\..\research\librtmp\srs_detect_rtmp.c,