From 3358570be64f20ac88be3318e7a0c0043a3681ae Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 8 Nov 2014 10:44:00 +0800 Subject: [PATCH] refine for bug#66, implements the usage. --- trunk/research/librtmp/srs_h264_raw_publish.c | 20 ++++--- trunk/src/app/srs_app_avc_aac.cpp | 2 +- trunk/src/kernel/srs_kernel_error.hpp | 1 + trunk/src/libs/srs_librtmp.cpp | 59 ++++++++++++++++--- trunk/src/libs/srs_librtmp.hpp | 1 + 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/trunk/research/librtmp/srs_h264_raw_publish.c b/trunk/research/librtmp/srs_h264_raw_publish.c index c51b930a4..f36c33207 100644 --- a/trunk/research/librtmp/srs_h264_raw_publish.c +++ b/trunk/research/librtmp/srs_h264_raw_publish.c @@ -37,7 +37,7 @@ gcc srs_h264_raw_publish.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_h #define srs_trace(msg, ...) printf(msg, ##__VA_ARGS__);printf("\n") -int read_h264_frame(char* data, int size, char** pp, int fps, +int read_h264_frame(char* data, int size, char** pp, int* pnb_start_code, int fps, char** frame, int* frame_size, int* dts, int* pts) { char* p = *pp; @@ -45,8 +45,7 @@ int read_h264_frame(char* data, int size, char** pp, int fps, // @remark, for this demo, to publish h264 raw file to SRS, // we search the h264 frame from the buffer which cached the h264 data. // please get h264 raw data from device, it always a encoded frame. - int pnb_start_code = 0; - if (!srs_h264_startswith_annexb(p, size - (p - data), &pnb_start_code)) { + if (!srs_h264_startswith_annexb(p, size - (p - data), pnb_start_code)) { srs_trace("h264 raw data invalid."); return -1; } @@ -55,10 +54,10 @@ int read_h264_frame(char* data, int size, char** pp, int fps, // each frame prefixed h.264 annexb header, by N[00] 00 00 01, where N>=0, // for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40) *frame = p; - p += pnb_start_code; + p += *pnb_start_code; for (;p < data + size; p++) { - if (srs_h264_startswith_annexb(p, size - (p - data), &pnb_start_code)) { + if (srs_h264_startswith_annexb(p, size - (p - data), NULL)) { break; } } @@ -160,7 +159,10 @@ int main(int argc, char** argv) // @remark, read a frame from file buffer. char* data = NULL; int size = 0; - if (read_h264_frame(h264_raw, file_size, &p, fps, &data, &size, &dts, &pts) < 0) { + int nb_start_code = 0; + if (read_h264_frame(h264_raw, file_size, &p, &nb_start_code, fps, + &data, &size, &dts, &pts) < 0 + ) { srs_trace("read a frame from file buffer failed."); goto rtmp_destroy; } @@ -173,9 +175,9 @@ int main(int argc, char** argv) // 5bits, 7.3.1 NAL unit syntax, // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. - u_int8_t nut = (char)data[0] & 0x1f; - srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d, b[0]=%#x(%s)", - srs_type2string(SRS_RTMP_TYPE_VIDEO), dts, size, fps, (char)data[0], + u_int8_t nut = (char)data[nb_start_code] & 0x1f; + srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d, b[%d]=%#x(%s)", + srs_type2string(SRS_RTMP_TYPE_VIDEO), dts, size, fps, nb_start_code, (char)data[nb_start_code], (nut == 7? "SPS":(nut == 8? "PPS":(nut == 5? "I":(nut == 1? "P":"Unknown"))))); // @remark, when use encode device, it not need to sleep. diff --git a/trunk/src/app/srs_app_avc_aac.cpp b/trunk/src/app/srs_app_avc_aac.cpp index 3f5ce2cb0..182da61ae 100644 --- a/trunk/src/app/srs_app_avc_aac.cpp +++ b/trunk/src/app/srs_app_avc_aac.cpp @@ -531,7 +531,7 @@ int SrsAvcAacCodec::avc_demux_annexb_format(SrsStream* stream, SrsCodecSample* s // get the last matched NALU while (!stream->empty()) { - if (srs_avc_startswith_annexb(stream, &nb_start_code)) { + if (srs_avc_startswith_annexb(stream, NULL)) { break; } diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 4eb2f3426..21ca885de 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -184,6 +184,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_KERNEL_STREAM_INIT 3038 #define ERROR_EDGE_VHOST_REMOVED 3039 #define ERROR_HLS_AVC_TRY_OTHERS 3040 +#define ERROR_H264_API_NO_PREFIXED 3041 /** * whether the error code is an system control error. diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index e0bb223e7..06a183b83 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -70,6 +70,10 @@ struct Context SimpleSocketStream* skt; int stream_id; + // for h264 raw stream, + // see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521 + SrsStream raw_stream; + Context() { rtmp = NULL; skt = NULL; @@ -995,15 +999,6 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) return any->human_print(pdata, psize); } - -int srs_write_h264_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_int32_t dts, u_int32_t pts) -{ - int ret = ERROR_SUCCESS; - - srs_assert(frames_size > 1); - - srs_assert(rtmp != NULL); - Context* context = (Context*)rtmp; /*// 5bits, 7.3.1 NAL unit syntax, // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. @@ -1051,6 +1046,52 @@ int srs_write_h264_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_ *p++ = pp[2]; *p++ = pp[1]; *p++ = pp[0];*/ + +int srs_write_h264_raw_frame(Context* context, char* frame, int frame_size, u_int32_t dts, u_int32_t pts) +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int srs_write_h264_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_int32_t dts, u_int32_t pts) +{ + int ret = ERROR_SUCCESS; + + srs_assert(frames_size > 1); + + srs_assert(rtmp != NULL); + Context* context = (Context*)rtmp; + + if ((ret = context->raw_stream.initialize(frames, frames_size)) != ERROR_SUCCESS) { + return ret; + } + + // send each frame. + while (!context->raw_stream.empty()) { + // each frame must prefixed by annexb format. + // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. + int pnb_start_code = 0; + if (!srs_avc_startswith_annexb(&context->raw_stream, &pnb_start_code)) { + return ERROR_H264_API_NO_PREFIXED; + } + int start = context->raw_stream.pos() + pnb_start_code; + + // find the last frame prefixed by annexb format. + context->raw_stream.skip(pnb_start_code); + while (!context->raw_stream.empty()) { + if (srs_avc_startswith_annexb(&context->raw_stream, NULL)) { + break; + } + context->raw_stream.skip(1); + } + int size = context->raw_stream.pos() - start; + + // send out the frame. + char* frame = context->raw_stream.data() + start; + if ((ret = srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) { + return ret; + } + } return ret; } diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index bb07e3bb0..6406b0118 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -342,6 +342,7 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); * frames can be one or more than one frame, * each frame prefixed h.264 annexb header, by N[00] 00 00 01, where N>=0, * for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40) +* about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. * @paam frames_size the size of h264 raw data. * assert frames_size > 1, at least has 1 bytes header. * @param dts the dts of h.264 raw data.