uvc camera yuv422 planer格式编码h264测试例程

/*

 
最简单的基于X264的视频编码器

  Simplest X264 Encoder

 
jiangyu

  

 
本程序可以YUV格式的像素数据编码为H.264码流,是最简单的

  基于libx264的视频编码器

 


  This software encode YUV data to H.264 bitstream.

 
It's the simplest encoder example based on libx264.

 */

include <stdio.h>

include <stdlib.h>

 

include "stdint.h"

 

if defined ( __cplusplus)

extern "C"

{

include "x264.h"

};

else

include "x264.h"

endif

 

int width=640;

int height=480;

int csp=X264_CSP_I422;

 // nv12 转 yuv 并写入本地

 #if 0

void nv12toYuv(uint8_t NV12, uint8_t I420,size_t pixelWidth,size_t pixelHeight,const char resultCString,const char resultCString2){

    unsigned char ybuf = (unsigned char )malloc(pixelHeight pixelWidth);

    unsigned char
ubuf = (unsigned char )malloc((pixelHeight/2) (pixelWidth/2));

    unsigned char vbuf = (unsigned char )malloc((pixelHeight/2) (pixelWidth/2));

    unsigned char
y = ybuf;

    unsigned char u = ubuf;

    unsigned char
v = vbuf;

    int len = (int)pixelHeight pixelWidth + pixelHeight pixelWidth / 2;

    FILE fpyuv = fopen(resultCString, "wb");

    for (int i = 0; i < len; i ++) {

        if (i < (pixelWidth
pixelHeight)) {  //yyyyy

            y = NV12;

            y++;

        }

        else{//uvuvuv

            if (i % 2 == 0) {//uuuuu

                u = NV12;

                u ++;

            }else{//vvvvv

                v = NV12;

                v ++;

            }

        }

        NV12 ++;

    }

    fwrite(ybuf, 1, pixelWidthpixelHeight, fpyuv);

    fwrite(ubuf, 1, pixelWidth
pixelHeight/4, fpyuv);

    fwrite(vbuf, 1, pixelWidth*pixelHeight/4, fpyuv);

    fclose(fpyuv);

    free(ybuf);

    free(ubuf);

    free(vbuf);

}






endif

//未用到

int yuv422toyuv420(unsigned char out, const unsigned char in, unsigned int width, unsigned int height)

{

unsigned char y = out;

unsigned char
u = out + widthheight;

unsigned char
v = out + widthheight + widthheight/4;



unsigned int i,j;

unsigned int base_h;

unsigned int is_y = 1, is_u = 1;

unsigned int y_index = 0, u_index = 0, v_index = 0;



unsigned long yuv422_length = 2 width height;



//序列为YU YV YU YV,一个yuv422帧的长度 width height 2 个字节

//丢弃偶数行 u v



for(i=0; i<yuv422_length; i+=2){

(y+y_index) = (in+i);

y_index++;

}



for(i=0; i<height; i+=2){

base_h = iwidth2;

for(j=base_h+1; j<base_h+width2; j+=2){

if(is_u){

(u+u_index) = (in+j);

u_index++;

is_u = 0;

}

else{

(v+v_index) = *(in+j);

v_index++;

is_u = 1;

}

}

}



return 1;

}

int main(int argc, char* argv)

{

 

         int ret;

         int y_size;

         int i,j,ii,len;

         char
tmpbuf = NULL;



         FILE fp_src  = fopen("./640x480.yuv", "rb");

         FILE
fp_dst = fopen("output.h264", "wb");



//Encode frame number

         //if set 0, encode all frame

         int frame_num=0;

         int index_y, index_u, index_v;

     int num;

         int iNal   = 0;

         x264_nal_t pNals = NULL;

         x264_t
pHandle   = NULL;

         x264_picture_t pPic_in = (x264_picture_t)malloc(sizeof(x264_picture_t));//编码之前进行填充

         x264_picture_t pPic_out = (x264_picture_t)malloc(sizeof(x264_picture_t));

         x264_param_t pParam = (x264_param_t)malloc(sizeof(x264_param_t));

        tmpbuf =  (char )malloc(widthheight2sizeof(char)+1);

if(!tmpbuf)

{

printf("malloc");

}

         //Check

         if(fp_src==NULL||fp_dst==NULL){

                   printf("Error open files.\n");

                   return -1;

         }

 

         x264_param_default(pParam);   //给参数结构体赋默认值

         x264_param_default_preset(pParam, "fast" , "zerolatency" );  //设置preset和tune

char y = pPic_in->img.plane[0];   

char
u = pPic_in->img.plane[1];   

char v = pPic_in->img.plane[2];

         //修改部分参数

         pParam->i_csp=csp;

         pParam->i_width   = width;   // 宽度

         pParam->i_height  = height;  // 高度

         pParam->i_fps_num  = 25;     // 设置帧率(分子)

         pParam->i_fps_den  = 1;      // 设置帧率时间1s(分母)

         

         pParam->i_threads  = X264_SYNC_LOOKAHEAD_AUTO;

         pParam->i_keyint_max = 10;              //在此间隔设置IDR关键帧

 

         pParam->rc.i_bitrate = 1200;       // 设置码率,在ABR(平均码率)模式下才生效,且必须在设置ABR前先设置bitrate

         pParam->rc.i_rc_method = X264_RC_ABR;  // 码率控制方法,CQP(恒定质量),CRF(恒定码率,缺省值23),ABR(平均码率)

         

         /


         //Param

         pParam->i_log_level  = X264_LOG_DEBUG;

         pParam->i_frame_total = 0;

         pParam->i_bframe  = 5;

         pParam->b_open_gop  = 0;

         pParam->i_bframe_pyramid = 0;

         pParam->rc.i_qp_constant=0;

         pParam->rc.i_qp_max=0;

         pParam->rc.i_qp_min=0;

         pParam->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;

         pParam->i_timebase_den = pParam->i_fps_num;

         pParam->i_timebase_num = pParam->i_fps_den;

         /

 

         //set profile  x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 };

if(csp == X264_CSP_I420)

         x264_param_apply_profile(pParam, "baseline");

         else if(csp == X264_CSP_I422)

         x264_param_apply_profile(pParam, "high422");

         //open encoder

         pHandle = x264_encoder_open(pParam);

          

  

  if(csp == X264_CSP_NV12){

pPic_in->img.i_stride[0] = pParam->i_width;

pPic_in->img.i_stride[1] = pParam->i_width;

pPic_in->img.i_stride[2] = 0;

pPic_in->img.i_csp = X264_CSP_NV12;

pPic_in->img.i_plane = 2;

} else if(csp == X264_CSP_I422)

{

 

pPic_in->img.i_csp = X264_CSP_I422;

pPic_in->img.i_plane = 3;

}else { // 其他暂认为都是YUV420格式

pPic_in->img.i_stride[0] = pParam->i_width;

pPic_in->img.i_stride[1] = pParam->i_width>>1;

pPic_in->img.i_stride[2] = pParam->i_width>>1;

pPic_in->img.i_csp = X264_CSP_I420;

pPic_in->img.i_plane = 3;

    } 

         x264_picture_init(pPic_out);





         x264_picture_alloc(pPic_in, csp, pParam->i_width, pParam->i_height);

 

         ret = x264_encoder_headers(pHandle, &pNals, &iNal);

 

         y_size = pParam->i_width
pParam->i_height;

         //detect frame number

         if(frame_num==0){

                   fseek(fp_src,0,SEEK_END);

                   switch(csp){

                   case X264_CSP_I444:frame_num=ftell(fp_src)/(y_size3);break;

                   case X264_CSP_I422:frame_num=ftell(fp_src)/(y_size
2);break;

                   case X264_CSP_I420:frame_num=ftell(fp_src)/(y_size3/2);break;

   case X264_CSP_NV12:frame_num=ftell(fp_src)/(y_size
3/2);break;

                   default:printf("Colorspace Not Support.\n");return -1;

                   }

                   fseek(fp_src,0,SEEK_SET);

         }

        printf("franme count   :%d \n",frame_num);

         //Loop to Encode

         for( i=0;i<frame_num;i++){

                   switch(csp){

                   case X264_CSP_I420:{

                            fread(pPic_in->img.plane[0],y_size,1,fp_src);         //Y

                            fread(pPic_in->img.plane[1],y_size/4,1,fp_src);       //U

                            fread(pPic_in->img.plane[2],y_size/4,1,fp_src);       //V

                            break;}

case X264_CSP_NV12:

         printf("nv12 enc y\n");

fread(pPic_in->img.plane[0],y_size,1,fp_src);         //Y

fread(pPic_in->img.plane[1],y_size/2,1,fp_src);      //uv

printf("nv12 enc uv end\n");

break;

case X264_CSP_I422:

    printf("i422 enc yuv start\n");

index_y = 0;

index_u = 0;

index_v = 0;

len =fread(tmpbuf,y_size2,1,fp_src); 

printf("read len:%d  %x %x\n",len,tmpbuf[0],tmpbuf[y_size
2]);

 

num = width height 2 - 4  ;

for(ii=0; ii<num; ii=ii+4)

{

(pPic_in->img.plane[0]+index_y++)  = tmpbuf[ii];

(pPic_in->img.plane[1] +index_u++) = tmpbuf[ii + 1];

(pPic_in->img.plane[0] +index_y++) = tmpbuf[ii + 2];

(pPic_in->img.plane[2] +index_v++) = tmpbuf[ii + 3];

}

break;

                   default:{

                            printf("Colorspace Not Support.\n");

                            return -1;}

                   }

                   pPic_in->i_pts = i;

 

                   ret = x264_encoder_encode(pHandle, &pNals, &iNal, pPic_in, pPic_out);

                   if (ret< 0){

                            printf("Error.\n");

                            return -1;

                   }

 

                   printf("Succeed encode frame: %5d\n",i);

 

                   for ( j = 0; j < iNal; ++j){

                             fwrite(pNals[j].p_payload, 1, pNals[j].i_payload, fp_dst);

                   }

         }

         i=0;

         //flush encoder

        / while(1){

                   ret = x264_encoder_encode(pHandle, &pNals, &iNal, NULL, pPic_out);

                   if(ret==0){

                            break;

                   }

                   printf("Flush 1 frame.\n");

                   for (j = 0; j < iNal; ++j){

                            fwrite(pNals[j].p_payload, 1, pNals[j].i_payload, fp_dst);

                   }

                   i++;

         }
/

         x264_picture_clean(pPic_in);

         x264_encoder_close(pHandle);

         pHandle = NULL;

 

         free(pPic_in);

         free(pPic_out);

         free(pParam);

free(tmpbuf);

 

         fclose(fp_src);

         fclose(fp_dst);

 

         return 0;

}

makefile 

##### Make sure all is the first target.
all:

CXX ?= g++
CC  ?= gcc

CFLAGS  += -g -pthread -Wall 
CFLAGS  += -rdynamic -funwind-tables

CFLAGS  +=  -I${SDKTARGETSYSROOT}/usr/include/linux-headers/usr/include 
CFLAGS  += -I./inc    
CFLAGS  += -I./usr/include

CFLAGS += -D__unused="__attribute__((__unused__))"

#LDFLAGS += -L./usr/lib/gpac
LDFLAGS += -lx264 -ldl

LDFLAGS += -L./usr/lib/



C_SRC=
C_SRC+=src/main.c
C_SRC+=src/osp.c
C_SRC+=src/osp_common.c
C_SRC+=src/osp_proc_data.c
C_SRC+=src/osp_syslog.c
C_SRC+=src/osp_timer.c
CXX_SRC=
OBJ=
DEP=


#LDFLAGS+= -lcamera

OBJ_CAM_SRV = src/main.o
TARGETS    += camera-rtp-service
$(TARGETS): $(OBJ_CAM_SRV)
TARGET_OBJ += $(OBJ_CAM_SRV)

FILE_LIST := files.txt
COUNT := ./make/count.sh
MK := $(word 1,$(MAKEFILE_LIST))
ME := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))

OBJ=$(CXX_SRC:.cpp=.o) $(C_SRC:.c=.o)
DEP=$(OBJ:.o=.d) $(TARGET_OBJ:.o=.d)

CXXFLAGS += -std=c++11 $(CFLAGS)
#include ./common.mk
.PHONY: all clean distclean

all: $(TARGETS)

clean:
rm -f $(TARGETS) $(FILE_LIST)
find . -name "*.o" -delete
find . -name "*.d" -delete

distclean:
rm -f $(TARGETS) $(FILE_LIST)
find . -name "*.o" -delete
find . -name "*.d" -delete

-include $(DEP)

%.o: %.c $(MK) $(ME)
@[ -f $(COUNT) ] && $(COUNT) $(FILE_LIST) $^ || true
@$(CC) -c $< -MM -MT $@ -MF $(@:.o=.d) $(CFLAGS) $(LIBQCAM_CFLAGS)
$(CC) -c $< $(CFLAGS) -o $@ $(LIBQCAM_CFLAGS)

%.o: %.cpp $(MK) $(ME)
@[ -f $(COUNT) ] && $(COUNT) $(FILE_LIST) $^ || true
@$(CXX) -c $< -MM -MT $@ -MF $(@:.o=.d) $(CXXFLAGS)
$(CXX) -c $< $(CXXFLAGS) -o $@

$(TARGETS): $(OBJ)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LDFLAGS)
@[ -f $(COUNT) -a -n "$(FILES)" ] && $(COUNT) $(FILE_LIST) $(FILES) || true
@[ -f $(COUNT) ] && $(COUNT) $(FILE_LIST) || true

QQ截图20190905105827.png

使用说明


本例程是基于uvc摄像头输出格式为yuv422 格式的并非 yuv2,所以3个planer.make file 中需要制定Linux的sdk路径。

sitemap