若该文为原创文章,转载请注明原文出处
编译librtmp库,及代码详解测试。
1、硬件:T31X+SC5235
2、开发环境: ubuntu16.04-64bit
3、编译器:mips-gcc540-glibc222-32bit-r3.3.0.tar.gz
注:板子和和WIFI模块是某淘上淘的,使用的是RTL8188,使用的是USB接口,uboot和内核是自己裁剪移植的,内核默认自带WIFI驱动,所以不用移植可以直接使用。
在交叉编译之前,要确保交叉编译链安装正常。
交叉编译librtmp需要编译zlib,openssl .
- 1、获取源码
- wget http://zlib.net/zlib-1.2.11
- 2、解压
- tar -vxf zlib-1.2.11
- 3、进入目录
- cd zlib
- 4、设置环境,输入以下命令
- CC=mips-linux-gnu-gcc ./configure --prefix=/usr/local
- 5、编译
- make
- 6、安装
- make install
-
- 执行成功后会在/usr/local下生成库.
- 1、下载源码
- get http://www.openssl.org/source/openssl-1.0.1u
- 2、解压
- tar -vxf openssl-1.0.1u
- 3、进入openssl目录
- cd openssl-1.0.1.u
- 4、设置环境,输入以下命令
- CC=mips-linux-gnu-gcc ./config no-asm shared --prefix=/usr/local
- 5、编译
- make
- 6、安装
- make install
- 1、下载源码
- git clone git://git.ffmpeg.org/rtmpdump
- 2、修改Makefile
- 1)、主要修改:
- CC=$(CROSS_COMPILE)gcc
- LD=$(CROSS_COMPILE)ld
- AR=$(CROSS_COMPILE)ar
- 修改成:
- CC=mips-linux-gnu-gcc
- LD=mips-linux-gnu-ld
- AR=mips-linux-gnu-ar
- 2)、修改CRYPTO=OPENSSL
- 修改为:
- CRYPTO=/usr/local/bin
- 3、编译
- make
- 4、安装
- make install
编译代码需要用到的库,本人在T31上使用的是静态库,可以自行改成动态库,以减少编译文件的大小 。
编译所需的库有:librtmp.a、libssl.a、libcrypto.a、libz.a
代码:
- /*!
- *****************************************************************************
- *
- * Copyright ? 2017-2018 yifeng. All Rights Reserved.
- *
- * \file main.c
- * \author yifeng
- * \version 1.0
- * \date 2022年3月3日
- * \brief rtmp测试代码
- *
- *----------------------------------------------------------------------------
- * \attention
- *
- *
- *****************************************************************************
- */
- /*****************************************************************************
- change history:
- 1.date : 2022年3月3日
- author: yifeng
- change: create file
-
- *****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <limits.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <arpa/inet.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <time.h>
- #include <unistd.h>
- #include <signal.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <netinet/in.h>
- #include <pthread.h>
- #include <stdbool.h>
-
- /* 环形队列头文件 */
- #include "ringfifo.h"
- #include "faac/faac.h"
- #include "xiecc_rtmp.h"
-
- #include <imp/imp_audio.h>
-
- #include <imp/imp_log.h>
-
- #define AAC_ADTS_HEADER_SIZE 7
-
- static uint32_t find_start_code(uint8_t *buf, uint32_t zeros_in_startcode)
- {
- uint32_t info;
- uint32_t i;
-
- info = 1;
- if ((info = (buf[zeros_in_startcode] != 1)? 0: 1) == 0)
- return 0;
-
- for (i = 0; i < zeros_in_startcode; i++)
- if (buf[i] != 0)
- {
- info = 0;
- break;
- };
-
- return info;
- }
-
- uint8_t * get_nal(uint32_t *len, uint8_t **offset, uint8_t *start, uint32_t total)
- {
- uint32_t info;
- uint8_t *q ;
- uint8_t *p = *offset;
- *len = 0;
- while(1) {
- info = find_start_code(p, 3);
- if (info == 1)
- break;
- p++;
- if ((p - start) >= total)
- return NULL;
- }
- q = p + 4;
- p = q;
- while(1) {
- info = find_start_code(p, 3);
- if (info == 1)
- break;
- p++;
- if ((p - start) >= total)
- return NULL;
- }
-
- *len = (p - q);
- *offset = p;
- return q;
- }
- uint8_t *get_adts(uint32_t *len, uint8_t **offset, uint8_t *start, uint32_t total)
- {
- uint8_t *p = *offset;
- uint32_t frame_len_1;
- uint32_t frame_len_2;
- uint32_t frame_len_3;
- uint32_t frame_length;
-
- if (total < AAC_ADTS_HEADER_SIZE) {
- return NULL;
- }
- if ((p - start) >= total) {
- return NULL;
- }
-
- if (p[0] != 0xff) {
- return NULL;
- }
- if ((p[1] & 0xf0) != 0xf0) {
- return NULL;
- }
- frame_len_1 = p[3] & 0x03;
- frame_len_2 = p[4];
- frame_len_3 = (p[5] & 0xe0) >> 5;
- frame_length = (frame_len_1 << 11) | (frame_len_2 << 3) | frame_len_3;
- *offset = p + frame_length;
- *len = frame_length;
- return p;
- }
-
-
- /*!
- * \fn main
- * \brief 主函数
- *
- * \param [in] int argc #
- * \param [in] char *argv[] #
- *
- * \retval int
- */
- int main(int argc, char *argv[])
- {
- pthread_t id;
- pthread_t audio_id;
-
- char serverStrBuf[100];
-
- if(argc != 2)
- {
- printf("Usage: rtmp serverip -eg << rtmp 192.168.1.100 >>");
- return -1;
- }
-
- sprintf(serverStrBuf, "rtmp://%s/live/stream", argv[1]);
- printf("Server=%s\n", serverStrBuf);
-
- /* 初始化内存 */
- ringmalloc(384*1024);
-
- void*p = rtmp_sender_alloc(serverStrBuf);
- if(rtmp_sender_start_publish(p, 0, 0) != 0)
- {
- printf("connect %s failed\n", serverStrBuf);
- return -1;
- }
-
- int fd = open("cms.264", O_RDONLY);
- uint8_t * buf = malloc(3 *1024 * 1024);
- uint32_t total;
- total = read(fd, buf, (1024*1024 *3));
- close(fd);
- int aacfd = open("audiotest.aac", O_RDONLY);
- uint8_t * audio_buf = malloc(1 *1024 * 1024);
- uint32_t audio_total;
- audio_total = read(aacfd, audio_buf, (1024*1024 *3));
- close(aacfd);
- uint8_t *buf_offset = buf;
- uint8_t *audio_buf_offset = audio_buf;
- uint32_t len;
- uint32_t audio_len;
- uint8_t *p_video ;
- uint8_t *pp;
- uint8_t *p_audio;
- uint32_t audio_ts = 0;
- uint32_t ts = 0;
- uint32_t len_1;
- uint32_t len_2;
- while (1) {
- p_audio = get_adts(&audio_len, &audio_buf_offset, audio_buf, audio_total);
- if (p_audio == NULL){
- audio_buf_offset = audio_buf;
- continue;
- }
- rtmp_sender_write_audio_frame(p, p_audio, audio_len, audio_ts);
-
- p_video = get_nal(&len, &buf_offset, buf, total);
- if (p_video == NULL) {
- buf_offset = buf;
- continue;
- }
- printf("%x %d\n", p_video[0], len);
- if (p_video[0] == 0x67) {
- pp = get_nal(&len_1, &buf_offset, buf, total);
- printf("%x %d\n", pp[0], len_1);
- pp = get_nal(&len_2, &buf_offset, buf, total);
- printf("%x %d\n", pp[0], len_2);
- uint8_t temp = len + len_1 + len_2 + 12;
- printf("temp %d\n", temp);
- rtmp_sender_write_video_frame(p, p_video - 4, temp, ts, 0);
- }
- else
- rtmp_sender_write_video_frame(p, p_video - 4, len + 4, ts, 0);
- ts += 50;
- audio_ts += 50;
- usleep(50 * 1000);
- }
-
- return 0;
- }
-
代码功能主要是读取h264和AAC文件,封装后,通过rtmp传到服务器,服务器可以用SRS,nginx等,具体服务器搭建不在演示。
把代码编译成可执行文件,运行测试。
1、主要是测试和了解下rtmp的推流方式,由于硬件显示,不测试拉流。
如有侵权,请及时联系博主删除,VX:18750903063