ortp学习笔记

URL:http://blog.csdn.net/ajaxhe/article/details/7753239


ortp版本:ortp-0.18.0.tar.gz  

操作系统:window 7 32bit

1.windows下编译ortp.lib
直接打开ortp-0.18.0\build\win32native的工程文件即可,VS2008下无需任何修改,即可编译出动态链接库 ortp.lib以及ortp.dll。

2.使用ortp提供的测试程序:ortp-0.18.0\src\tests下的win_receive以及win_sender目录下程序
在windows7下使用win_receiver时会提示下如下错误,这个在错误在windows XP下是不存在的
QOSAddSocketToFlow failed to add a flow with error 87
具体问题暂时还没有深究,这个应该是一个系统兼容性问题,需要系统支持qwave.lib。
在查找了错误出处,对比了前几个ortp的版本后,对ortp0.18的源代码进行了修改
rtp_session_inet.c
/* set socket options (but don't change chosen states) */
/*
          rtp_session_set_dscp( session, -1 );
          rtp_session_set_multicast_ttl( session, -1 );
          rtp_session_set_multicast_loopback( session, -1 );
*/

3. 发送H.264视频帧
ortp提供的win_receive以及win_sender一次只发送160字节的数据。但我们在发送一帧H.264视频帧,每次需要发送2000-3000字节的数据,关于ortp发送H.264视频帧,可以参考:
ortp编程示例代码
谈谈RTP传输中的负载类型和时间戳
除了上面两篇文章提到需要注意的负载类型和时间戳之外,在ortp中win_receive中还需要显示调用:
rtp_session_set_recv_buf_size(rtp_session_mgr .rtp_session , recv_bufsize);
这里的recv_bufsize必须要比win_sender中
sended_bytes = rtp_session_send_with_ts (rtp_session_mgr .rtp_session ,
                          ( uint8_t *) send_buffer,
                           wrapLen,
                          rtp_session_mgr.cur_timestamp );
的wrapLen要大,否则在receive端会出现如下错误:
ortp-warning-Error receiving RTP packet: Error code : 10040, err num [10040],error [-1]


4. 一个结合H.264编码,rtp发送,接收,保存mp4文件的小程序

下载地址:ortp测试程序(修改版)

编译环境:vs2008
压缩文件中包括了ffmpeg以及ortp的动态链接库,但你还需要在工程文件中修改它们的路径才能正确链接这两个库.
因为这个小程序是一个项目的一部分,源代码中还有些冗余代码,并没有来的及删掉,大家在看的时候需要注意下

receiver
[cpp]  view plain copy
  1. #include   
  2. #include "ortp/ortp.h"  
  3.   
  4. extern "C"{  
  5. #include   
  6. #include   
  7. };  
  8.   
  9. bool m_bExit = FALSE;  
  10.   
  11. struct RtpSessionMgr  
  12. {  
  13.     RtpSession *rtp_session;  
  14.     int timestamp;  
  15. };  
  16.   
  17.   
  18. RtpSessionMgr rtp_session_mgr;  
  19. const int timestamp_inc = 3600; // 90000/25  
  20.   
  21. const char recv_ip[] = "127.0.0.1";  
  22. const int recv_port = 8008;  
  23. const int recv_bufsize = 10240;  
  24. unsigned char *recv_buf;  
  25.   
  26. /** 帧包头的标识长度 */   
  27. #define CMD_HEADER_LEN 10  
  28.   
  29. /** 帧包头的定义 */  
  30. static uint8_t CMD_HEADER_STR[CMD_HEADER_LEN] = { 0xAA,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xFF };  
  31.   
  32. /** 帧的包头信息 */  
  33. typedef struct _sFrameHeader  
  34. {  
  35.     /** 命令名称标识 */   
  36.     unsigned char cmdHeader[CMD_HEADER_LEN];  
  37.   
  38.     /** 采集的通道号 0~7*/  
  39.     unsigned char chId;  
  40.   
  41.     /** 数据类型,音频 或者 视频*/  
  42.     unsigned char dataType;   
  43.   
  44.     /** 缓冲区的数据长度 */   
  45.     uint32_t len;  
  46.   
  47.     /** 时间戳 */  
  48.     uint32_t timestamp;  
  49.   
  50. }FrameHeader;  
  51.   
  52. ///////ffmpeg///////////////////////////////////////////////////////////////////  
  53. AVOutputFormat *fmt;  
  54. AVFormatContext *oc;  
  55. AVStream *video_st;  
  56. AVCodecContext *codecContext;  
  57.   
  58. const int image_width = 704;  
  59. const int image_height = 576;  
  60. const int frame_rate = 25;  
  61. static int frame_count;  
  62.   
  63. BOOL ctrlHandlerFunction(DWORD fdwCtrlType)   
  64. {   
  65.     switch (fdwCtrlType)   
  66.     {   
  67.         // Handle the CTRL+C signal.   
  68.         // CTRL+CLOSE: confirm that the user wants to exit.   
  69.     case CTRL_C_EVENT:   
  70.     case CTRL_CLOSE_EVENT:   
  71.     case CTRL_BREAK_EVENT:   
  72.     case CTRL_LOGOFF_EVENT:   
  73.     case CTRL_SHUTDOWN_EVENT:   
  74.         m_bExit = TRUE;  
  75.         return TRUE;   
  76.   
  77.     default:   
  78.         return FALSE;   
  79.     }   
  80. }   
  81.   
  82. void rtpInit()  
  83. {  
  84.     int ret;  
  85.     WSADATA wsaData;  
  86.   
  87.     /** 初始化winsocket */   
  88.     if ( WSAStartup(MAKEWORD(2,2), &wsaData) != 0)  
  89.     {  
  90.         fprintf(stderr, "WAStartup failed!\n");  
  91.         return ;  
  92.     }  
  93.   
  94.     ortp_init();  
  95.     ortp_scheduler_init();  
  96.   
  97.     rtp_session_mgr.rtp_session = rtp_session_new(RTP_SESSION_RECVONLY);  
  98.   
  99.     rtp_session_set_scheduling_mode(rtp_session_mgr.rtp_session, 1);  
  100.     rtp_session_set_blocking_mode(rtp_session_mgr.rtp_session, 1);  
  101.     rtp_session_set_local_addr(rtp_session_mgr.rtp_session, recv_ip, recv_port);  
  102.   
  103.     rtp_session_enable_adaptive_jitter_compensation(rtp_session_mgr.rtp_session, TRUE);  
  104.     rtp_session_set_jitter_compensation(rtp_session_mgr.rtp_session, 40);  
  105.   
  106.     rtp_session_set_payload_type(rtp_session_mgr.rtp_session, 34);  
  107.     rtp_session_set_recv_buf_size(rtp_session_mgr.rtp_session, recv_bufsize);  
  108.   
  109.     rtp_session_mgr.timestamp = timestamp_inc;  
  110. }  
  111.   
  112. int rtp2disk()  
  113. {  
  114.     int err;  
  115.     int havemore = 1;  
  116.   
  117.     while (havemore)  
  118.     {  
  119.         err = rtp_session_recv_with_ts(rtp_session_mgr.rtp_session,   
  120.                                         (uint8_t *)recv_buf, recv_bufsize,   
  121.                                         rtp_session_mgr.timestamp, &havemore);  
  122.   
  123.         if (havemore)   
  124.             printf("==> Warning: havemore=1!\n");  
  125.   
  126.         if (err > 0)  
  127.         {  
  128.             FrameHeader *frameHeader;  
  129.   
  130.             printf("receive data is %d\n", err);  
  131.               
  132.             frameHeader = (FrameHeader *)recv_buf;  
  133.             printf("frame_len = %d\n", frameHeader->len);  
  134.   
  135.             AVPacket pkt;  
  136.             av_init_packet(&pkt);  
  137.             pkt.stream_index= video_st->index;  
  138.             pkt.data= recv_buf + sizeof(FrameHeader);  
  139.             pkt.size = frameHeader->len; // not the video_outbuf_size, note!  
  140.             // write the compressed frame in the media file  
  141.             err = av_write_frame(oc, &pkt);  
  142.   
  143.             if (err != 0)  
  144.             {  
  145.                 printf("av_write_frame failed\n");  
  146.             }  
  147.         }  
  148.     }  
  149.   
  150.     return 0;  
  151. }  
  152.   
  153. AVCodecContext* createCodecContext(AVFormatContext *oc)  
  154. {  
  155.     AVCodecContext *video_cc = avcodec_alloc_context();  
  156.   
  157.     video_cc =  avcodec_alloc_context();  
  158.     if (!video_cc)  
  159.     {  
  160.         fprintf(stderr, "alloc avcodec context failed\n");  
  161.         exit(1);  
  162.     }  
  163.   
  164.     video_cc->codec_id = (CodecID)CODEC_ID_H264;  
  165.     video_cc->codec_type = AVMEDIA_TYPE_VIDEO;  
  166.   
  167.     video_cc->me_range = 16;    
  168.     video_cc->max_qdiff = 4;    
  169.     video_cc->qmin = 10;    
  170.     video_cc->qmax = 51;    
  171.     video_cc->qcompress = 0.6f;    
  172.   
  173.     /* put sample parameters */  
  174.     video_cc->bit_rate = 400000;  
  175.   
  176.     /* resolution must be a multiple of two */  
  177.     video_cc->width = image_width;  
  178.     video_cc->height = image_height;  
  179.   
  180.     /* time base: this is the fundamental unit of time (in seconds) in terms 
  181.     of which frame timestamps are represented. for fixed-fps content, 
  182.     timebase should be 1/framerate and timestamp increments should be 
  183.     identically 1. */  
  184.     video_cc->time_base.den = frame_rate;  
  185.     video_cc->time_base.num = 1;  
  186.   
  187.     video_cc->gop_size = 12; /* emit one intra frame every twelve frames at most */  
  188.     video_cc->pix_fmt = PIX_FMT_YUV420P;  
  189.   
  190.     // some formats want stream headers to be separate  
  191.     if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))  
  192.         video_cc->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  193.   
  194.     return video_cc;  
  195. }  
  196.   
  197. void openVideo(AVFormatContext *oc)  
  198. {  
  199.     AVCodec *codec;  
  200.   
  201.     /* find the video encoder */  
  202.     codec = avcodec_find_encoder(codecContext->codec_id);  
  203.     if (!codec) {  
  204.         fprintf(stderr, "codec not found\n");  
  205.         exit(1);  
  206.     }  
  207.   
  208.     /* open the codec */  
  209.     if (avcodec_open(codecContext, codec) < 0) {  
  210.         fprintf(stderr, "could not open video codec\n");  
  211.         exit(1);  
  212.     }  
  213. }  
  214.   
  215. void ffmpegEncodeInit()  
  216. {  
  217.     // initialize libavcodec, and register all codecs and formats  
  218.     av_register_all();  
  219.   
  220.     char filename[] = "test.mp4";  
  221.     fmt = av_guess_format(NULL, filename, NULL);  
  222.   
  223.     oc = avformat_alloc_context();  
  224.     oc->oformat = fmt;  
  225.   
  226.     fmt->video_codec = (CodecID) CODEC_ID_H264;  
  227.     _snprintf(oc->filename, sizeof(oc->filename), "%s", filename);  
  228.   
  229.     // add the video streams using the default format codecs and initialize the codecs  
  230.     video_st = NULL;  
  231.     if (fmt->video_codec != CODEC_ID_NONE) {  
  232.         video_st = av_new_stream(oc, 0);  
  233.         if (!video_st) {  
  234.             fprintf(stderr, "Could not alloc stream\n");  
  235.             exit(1);  
  236.         }  
  237.     }  
  238.   
  239.     // alloc codecContext  
  240.     codecContext = createCodecContext(oc);  
  241.     video_st->codec = codecContext;  
  242.   
  243.     // set the output parameters (must be done even if no parameters).  
  244.     if (av_set_parameters(oc, NULL) < 0) {  
  245.         fprintf(stderr, "Invalid output format parameters\n");  
  246.         exit(1);  
  247.     }  
  248.   
  249.     dump_format(oc, 0, filename, 1);  
  250.   
  251.     /* now that all the parameters are set, we can open the audio and 
  252.     video codecs and allocate the necessary encode buffers */  
  253.     if (codecContext)  
  254.         openVideo(oc);  
  255.   
  256.     // open the output file, if needed  
  257.     if (!(fmt->flags & AVFMT_NOFILE)) {  
  258.         if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {  
  259.             fprintf(stderr, "Could not open '%s'\n", filename);  
  260.             exit(1);  
  261.         }  
  262.     }  
  263.   
  264.     // write the stream header, if any  
  265.     av_write_header(oc);  
  266. }  
  267.   
  268. void ffmpegEncodeClose()  
  269. {  
  270.     int i;  
  271.   
  272.     /* close each codec */  
  273.     if (video_st)  
  274.         avcodec_close(video_st->codec);  
  275.   
  276.     // write the trailer, if any  
  277.     av_write_trailer(oc);  
  278.   
  279.     /* free the streams */  
  280.     for(i = 0; i < oc->nb_streams; i++) {  
  281.         av_freep(&oc->streams[i]->codec);  
  282.         av_freep(&oc->streams[i]);  
  283.     }  
  284.   
  285.     if (!(fmt->flags & AVFMT_NOFILE)) {  
  286.         /* close the output file */  
  287.         url_fclose(oc->pb);  
  288.     }  
  289.   
  290.     /* free the stream */  
  291.     av_free(oc);  
  292. }  
  293.   
  294. int main()  
  295. {  
  296.     recv_buf = (uint8_t *)malloc(recv_bufsize);  
  297.   
  298.     rtpInit();  
  299.     ffmpegEncodeInit();  
  300.   
  301.     // =============== INSTALL THE CONTROL HANDLER ===============  
  302.     if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ctrlHandlerFunction, TRUE) == 0)  
  303.     {  
  304.         printf("==> Cannot handle the CTRL-C...\n");  
  305.     }  
  306.   
  307.     printf("==> RTP Receiver started\n");  
  308.   
  309.     while (m_bExit == FALSE)  
  310.     {  
  311.         rtp2disk();  
  312.           
  313.         rtp_session_mgr.timestamp += timestamp_inc;  
  314.     }  
  315.   
  316.     printf("==> Exiting\n");  
  317.   
  318.     free(recv_buf);  
  319.   
  320.     ffmpegEncodeClose();  
  321.   
  322.     rtp_session_destroy(rtp_session_mgr.rtp_session);  
  323.     ortp_exit();  
  324. }  

sender
[cpp]  view plain copy
  1. #include   
  2. #include   
  3.   
  4. extern "C"{  
  5. #include   
  6. #include   
  7. };  
  8.   
  9. struct RtpSessionMgr  
  10. {  
  11.     RtpSession *rtp_session;  
  12.     uint32_t timestamp_inc;  
  13.     uint32_t cur_timestamp;  
  14. };  
  15.   
  16. RtpSessionMgr rtp_session_mgr;  
  17.   
  18. const char g_ip[] = "127.0.0.1";  
  19. const int g_port = 8008;  
  20. const uint32_t timestamp_inc = 3600; // 90000 / 25  
  21.   
  22. const int image_width = 704;  
  23. const int image_height = 576;  
  24. const int frame_rate = 25;  
  25. static int frame_count, wrap_size;  
  26.   
  27. AVCodecContext *video_cc;  
  28.   
  29. AVFrame *picture;  
  30.   
  31. /** 帧包头的标识长度 */   
  32. #define CMD_HEADER_LEN 10  
  33.   
  34. /** 帧包头的定义 */  
  35. static uint8_t CMD_HEADER_STR[CMD_HEADER_LEN] = { 0xAA,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xFF };  
  36.   
  37. /** 帧的包头信息 */  
  38. typedef struct _sFrameHeader  
  39. {  
  40.     /** 命令名称标识 */   
  41.     unsigned char cmdHeader[CMD_HEADER_LEN];  
  42.   
  43.     /** 采集的通道号 0~7*/  
  44.     unsigned char chId;  
  45.   
  46.     /** 数据类型,音频 或者 视频*/  
  47.     unsigned char dataType;   
  48.   
  49.     /** 缓冲区的数据长度 */   
  50.     uint32_t len;  
  51.   
  52.     /** 时间戳 */  
  53.     uint32_t timestamp;  
  54.   
  55. }FrameHeader;  
  56.   
  57. // set frame header   
  58. FrameHeader frameHeader;  
  59.   
  60. void rtpInit()  
  61. {  
  62.     char *m_SSRC;  
  63.   
  64.     ortp_init();  
  65.     ortp_scheduler_init();  
  66.     printf("Scheduler initialized\n");  
  67.   
  68.     rtp_session_mgr.rtp_session = rtp_session_new(RTP_SESSION_SENDONLY);  
  69.   
  70.     rtp_session_set_scheduling_mode(rtp_session_mgr.rtp_session, 1);  
  71.     rtp_session_set_blocking_mode(rtp_session_mgr.rtp_session, 1);  
  72.     rtp_session_set_remote_addr(rtp_session_mgr.rtp_session, g_ip, g_port);  
  73.     rtp_session_set_send_payload_type(rtp_session_mgr.rtp_session, 34); // 34 is for H.263 video frame  
  74.   
  75.     m_SSRC  = getenv("SSRC");  
  76.     if (m_SSRC != NULL)   
  77.     {  
  78.         rtp_session_set_ssrc(rtp_session_mgr.rtp_session, atoi(m_SSRC));  
  79.     }  
  80.   
  81.     rtp_session_mgr.cur_timestamp = 0;  
  82.     rtp_session_mgr.timestamp_inc = timestamp_inc;  
  83.   
  84.     printf("rtp init success!\n");  
  85. }  
  86.   
  87. int rtpSend(unsigned char *send_buffer, int frame_len)  
  88. {  
  89.     FrameHeader *fHeader = (FrameHeader *)send_buffer;  
  90.     fHeader->chId      = 0;  
  91.     fHeader->dataType  = 0; // SESSION_TYPE_VIDEO  
  92.     fHeader->len       = frame_len;  
  93.     fHeader->timestamp = 0;  
  94.   
  95.     printf("frame header len = %d\n", fHeader->len);  
  96.   
  97.     int wrapLen;  
  98.     wrapLen = frame_len + sizeof(FrameHeader);  
  99.   
  100.     int sended_bytes;  
  101.     sended_bytes = rtp_session_send_with_ts(rtp_session_mgr.rtp_session,   
  102.                                             (uint8_t *)send_buffer,   
  103.                                             wrapLen,  
  104.                                             rtp_session_mgr.cur_timestamp);  
  105.   
  106.     rtp_session_mgr.cur_timestamp += rtp_session_mgr.timestamp_inc;  
  107.   
  108.     return sended_bytes;  
  109. }  
  110.   
  111. void createCodecContext()  
  112. {  
  113.     video_cc =  avcodec_alloc_context();  
  114.     if (!video_cc)  
  115.     {  
  116.         fprintf(stderr, "alloc avcodec context failed\n");  
  117.         exit(1);  
  118.     }  
  119.   
  120.     video_cc->codec_id = (CodecID)CODEC_ID_H264;  
  121.     video_cc->codec_type = AVMEDIA_TYPE_VIDEO;  
  122.   
  123.     video_cc->me_range = 16;    
  124.     video_cc->max_qdiff = 4;    
  125.     video_cc->qmin = 10;    
  126.     video_cc->qmax = 51;    
  127.     video_cc->qcompress = 0.6f;    
  128.   
  129.     /* put sample parameters */  
  130.     video_cc->bit_rate = 400000;  
  131.   
  132.     /* resolution must be a multiple of two */  
  133.     video_cc->width = image_width;  
  134.     video_cc->height = image_height;  
  135.   
  136.     /* time base: this is the fundamental unit of time (in seconds) in terms 
  137.     of which frame timestamps are represented. for fixed-fps content, 
  138.     timebase should be 1/framerate and timestamp increments should be 
  139.     identically 1. */  
  140.     video_cc->time_base.den = frame_rate;  
  141.     video_cc->time_base.num = 1;  
  142.   
  143.     video_cc->gop_size = 12; /* emit one intra frame every twelve frames at most */  
  144.     video_cc->pix_fmt = PIX_FMT_YUV420P;  
  145. }  
  146.   
  147. AVFrame *allocPicture(int pix_fmt, int width, int height)  
  148. {  
  149.     AVFrame *picture;  
  150.     uint8_t *picture_buf;  
  151.     int size;  
  152.   
  153.     picture = avcodec_alloc_frame();  
  154.     if (!picture)  
  155.         return NULL;  
  156.       
  157.     size = avpicture_get_size((PixelFormat)pix_fmt, width, height);  
  158.     picture_buf = (uint8_t *)av_malloc(size);  
  159.     if (!picture_buf) {  
  160.         av_free(picture);  
  161.         return NULL;  
  162.     }  
  163.     avpicture_fill((AVPicture *)picture, picture_buf, (PixelFormat)pix_fmt, width, height);  
  164.     return picture;  
  165. }  
  166.   
  167. void openVideo()  
  168. {  
  169.     AVCodec *video_codec;  
  170.   
  171.     /* find the video encoder */  
  172.     video_codec = avcodec_find_encoder(video_cc->codec_id);  
  173.     if (!video_codec) {  
  174.         fprintf(stderr, "codec not found\n");  
  175.         exit(1);  
  176.     }  
  177.   
  178.     /* open the codec */  
  179.     if (avcodec_open(video_cc, video_codec) < 0) {  
  180.         fprintf(stderr, "could not open video codec\n");  
  181.         exit(1);  
  182.     }  
  183.   
  184.     /* allocate the encoded raw picture */  
  185.     picture = allocPicture(video_cc->pix_fmt, video_cc->width, video_cc->height);  
  186.     if (!picture) {  
  187.         fprintf(stderr, "Could not allocate picture\n");  
  188.         exit(1);  
  189.     }  
  190. }  
  191.   
  192. /* prepare a dummy image */  
  193. void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)  
  194. {  
  195.     int x, y, i;  
  196.   
  197.     i = frame_index;  
  198.   
  199.     /* Y */  
  200.     for(y=0;y
  201.         for(x=0;x
  202.             pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;  
  203.         }  
  204.     }  
  205.   
  206.     /* Cb and Cr */  
  207.     for(y=0;y
  208.         for(x=0;x
  209.             pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;  
  210.             pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;  
  211.         }  
  212.     }  
  213. }  
  214.   
  215. void ffmpegInit()  
  216. {  
  217.     // initialize libavcodec, and register all codecs and formats  
  218.     av_register_all();  
  219.   
  220.     // create a codec context  
  221.     createCodecContext();  
  222.   
  223.     // open H.264 codec  
  224.     openVideo();  
  225. }  
  226.   
  227. void getEncodedFrame(unsigned char *buffer, int& len)  
  228. {  
  229.     int out_size;  
  230.   
  231.     fill_yuv_image(picture, frame_count, video_cc->width, video_cc->height);  
  232.   
  233.     // encode the frame  
  234.     out_size = avcodec_encode_video(video_cc, buffer, wrap_size-sizeof(FrameHeader), picture);  
  235.   
  236.     len = out_size;  
  237.     frame_count++;  
  238. }  
  239.   
  240. int main()  
  241. {  
  242.     unsigned char *send_outbuf;  
  243.     unsigned char *video_part;  
  244.   
  245.     frame_count = 0;  
  246.     wrap_size = 20000;  
  247.     send_outbuf = (unsigned char *)malloc(wrap_size);  
  248.   
  249.     // copy cmdHeader to frameInfo  
  250.     memcpy(frameHeader.cmdHeader,CMD_HEADER_STR,CMD_HEADER_LEN);  
  251.   
  252.     memcpy(send_outbuf, &frameHeader, sizeof(FrameHeader));  
  253.     video_part = send_outbuf + sizeof(FrameHeader);  
  254.   
  255.     ffmpegInit();  
  256.     rtpInit();  
  257.   
  258.     while (1)  
  259.     {  
  260.         int frame_len;  
  261.         // get encode frame  
  262.         getEncodedFrame(video_part, frame_len);  
  263.   
  264.         printf("encodecFrame length is : %d\n", frame_len);  
  265.   
  266.         if (frame_len > 0)  
  267.         {  
  268.             rtpSend(send_outbuf, frame_len);  
  269.         }  
  270.     }  
  271.   
  272.     rtp_session_destroy(rtp_session_mgr.rtp_session);  
  273.   
  274.     free(send_outbuf);  
  275.   
  276.     // Give us some time  
  277.     Sleep(250);  
  278.   
  279.     ortp_exit();  
  280. }  

你可能感兴趣的:(rtsp/rtmp)