嵌入式设备上ffmpeg取摄像头+硬编码+rtmp推送

手中的板子的CPU是三星coretex-a9的,板子有硬编能力(至于是哪个芯片没仔细看),通过一至两周的努力,成功实现硬编码成H.264并投递到rtmp服务器。大体实现如下:

1.使用ffmpeg取摄像头YUV数据;

2.将YUV数据喂给三星硬编API;

3.将硬编的数据通过librtmp投递;

废话少说,上代码,代码有些糙,将就看:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>

#include <librtmp/rtmp.h>

#include <nx_fourcc.h>
#include <nx_vip.h>   // VIP
#include <nx_dsp.h>  // Display
#include "nx_video_api.h" // Video En/Decoder

#include "sps_decode.h"

#define MAX_FILE_NAME   1024
#define MAX_SEQ_BUF_SIZE  (4*1024)

//定义包头长度,RTMP_MAX_HEADER_SIZE=18
#define RTMP_HEAD_SIZE   (sizeof(RTMPPacket)+RTMP_MAX_HEADER_SIZE)
//存储Nal单元数据的buffer大小
#define BUFFER_SIZE 327680
#define MAX_PACKET_BYTES (RTMP_HEAD_SIZE+BUFFER_SIZE)
//搜寻Nal单元时的一些标志
#define GOT_A_NAL_CROSS_BUFFER BUFFER_SIZE+1
#define GOT_A_NAL_INCLUDE_A_BUFFER BUFFER_SIZE+2
#define NO_MORE_BUFFER_TO_READ BUFFER_SIZE+3
enum 

  VIDEO_CODECID_H264 = 7, 
}; 
/**
 * _NaluUnit
 * 内部结构体。该结构体主要用于存储和传递Nal单元的类型、大小和数据
 */
typedef struct _NaluUnit 

 int type; 
    int size; 
 unsigned char *data; 
}NaluUnit;

typedef struct _RTMPMetadata
{
 // video, must be h264 type
 unsigned int nWidth;
 unsigned int nHeight;
 unsigned int nFrameRate;  // fps
 unsigned int nVideoDataRate; // bps
 unsigned int nSpsLen;
 unsigned char* Sps;
 unsigned int nPpsLen;
 unsigned char* Pps;

 // audio, must be aac type
 bool         bHasAudio;
 unsigned int nAudioDatarate;
 unsigned int nAudioSampleRate;
 unsigned int nAudioSampleSize;
 int    nAudioFmt;
 unsigned int nAudioChannels;
 char      pAudioSpecCfg;
 unsigned int nAudioSpecCfgLen;

} RTMPMetadata,*LPRTMPMetadata;

static void dumpdata( void *data, int len, const char *msg )
{
 int i=0;
 unsigned char *byte = (unsigned char *)data;
 printf("Dump Data : %s", msg);
 for( i=0 ; i<len ; i ++ )
 {
  if( i!=0 && i%16 == 0 ) printf("\n\t");
  printf("%.2x", byte[i] );
  if( i%4 == 3 ) printf(" ");
 }
 printf("\n");
}


//网络字节序转换
char * put_byte( char *output, uint8_t nVal )   
{   
 output[0] = nVal;   
 return output+1;   
}  

char * put_be16(char *output, uint16_t nVal )   
{   
 output[1] = nVal & 0xff;   
 output[0] = nVal >> 8;   
 return output+2;   

char * put_be24(char *output,uint32_t nVal )   
{   
 output[2] = nVal & 0xff;   
 output[1] = nVal >> 8;   
 output[0] = nVal >> 16;   
 return output+3;   
}   
char * put_be32(char *output, uint32_t nVal )   
{   
 output[3] = nVal & 0xff;   
 output[2] = nVal >> 8;   
 output[1] = nVal >> 16;   
 output[0] = nVal >> 24;   
 return output+4;   
}   
char *  put_be64( char *output, uint64_t nVal )   
{   
 output=put_be32( output, nVal >> 32 );   
 output=put_be32( output, nVal );   
 return output;   

char * put_amf_string( char *c, const char *str )   
{   
 uint16_t len = strlen( str );   
 c=put_be16( c, len );   
 memcpy(c,str,len);   
 return c+len;   
}   
char * put_amf_double( char *c, double d )   
{   
 *c++ = AMF_NUMBER;  /* type: Number */   
 {   
  unsigned char *ci, *co;   
  ci = (unsigned char *)&d;   
  co = (unsigned char *)c;   
  co[0] = ci[7];   
  co[1] = ci[6];   
  co[2] = ci[5];   
  co[3] = ci[4];   
  co[4] = ci[3];   
  co[5] = ci[2];   
  co[6] = ci[1];   
  co[7] = ci[0];   
 }   
 return c+8;   

unsigned int g_nStop;

unsigned int  m_nFileBufSize;
unsigned int  nalhead_pos;
RTMP* m_pRtmp; 
RTMPMetadata g_metaData;
char m_pBuff[MAX_PACKET_BYTES];
unsigned char *m_pFileBuf; 
unsigned char *m_pFileBuf_tmp;
unsigned char* m_pFileBuf_tmp_old; //used for realloc

/**
 * 初始化并连接到服务器
 *
 * @param url 服务器上对应webapp的地址
 *     
 * @成功则返回1 , 失败则返回0
 */
int RTMP264_Connect(const char* url) 

 nalhead_pos=0;
 m_nFileBufSize=BUFFER_SIZE;
 m_pFileBuf=(unsigned char*)malloc(BUFFER_SIZE);
 m_pFileBuf_tmp=(unsigned char*)malloc(BUFFER_SIZE);

 m_pRtmp = RTMP_Alloc();
 RTMP_Init(m_pRtmp);
 /*设置URL*/
 if (RTMP_SetupURL(m_pRtmp,(char*)url) == FALSE)
 {
  RTMP_Free(m_pRtmp);
  return false;
 }
 /*设置可写,即发布流,这个函数必须在连接前使用,否则无效*/
 RTMP_EnableWrite(m_pRtmp);
 /*连接服务器*/
 if (RTMP_Connect(m_pRtmp, NULL) == FALSE)
 {
  RTMP_Free(m_pRtmp);
  return false;
 }

 /*连接流*/
 if (RTMP_ConnectStream(m_pRtmp,0) == FALSE)
 {
  RTMP_Close(m_pRtmp);
  RTMP_Free(m_pRtmp);
  return false;
 }
 return true; 


/**
 * 断开连接,释放相关的资源。
 *
 */   
void RTMP264_Close() 

 if(m_pRtmp) 
 { 
  RTMP_Close(m_pRtmp); 
  RTMP_Free(m_pRtmp); 
  m_pRtmp = NULL; 
 } 
 if (m_pFileBuf != NULL)
 { 
  free(m_pFileBuf);
 } 
 if (m_pFileBuf_tmp != NULL)
 { 
  free(m_pFileBuf_tmp);
 }
}

/**
 * 发送RTMP数据包
 *
 * @param nPacketType 数据类型
 * @param data 存储数据内容
 * @param size 数据大小
 * @param nTimestamp 当前包的时间戳
 *
 * @成功则返回 1 , 失败则返回一个小于0的数
 */
int SendPacket(unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp) 

    if(m_pRtmp == NULL) return -1;
 RTMPPacket* packet;
 /*分配包内存和初始化,len为包体长度*/
 packet = (RTMPPacket *)m_pBuff;
 
 /*包体内存*/
 packet->m_body = (char *)packet + RTMP_HEAD_SIZE;
 packet->m_nBodySize = size;
 //memcpy(packet->m_bod

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值