前面一篇博客介绍在centos上搭建点击打开链接ffmpeg及x264开发环境。以下就来问个样例:

1、利用x264库将YUV格式视频文件编码为h264格式视频文件

2、利用ffmpeh库将h264格式的视频文件解码为yuv格式视频文件

解码和编码前后对文件大小进行比較,如图:

当中yuv420p.yuv为原始文件,大小77M

encode.h264为H264编码后的视频文件,大小1.4M

decode.yuv为ffmpeg解码后的视频文件,大小77M。

从文件的大小非常明显能够看出h264压缩率。在Windows平台分辨播放了三个文件,画面看不出差别。

以下是代码"

/*File : yuvTO264.c
*Auth : sjin
*Date : 20141115
*Mail : 413977243@qq.com
*/ /*利用x264库将YUV文件编码为h264文件
*
*/ #include <stdint.h>
#include <x264.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h> #define CLEAR(x) (memset((&x),0,sizeof(x)))
#define IMAGE_WIDTH 176
#define IMAGE_HEIGHT 144
#define ENCODER_PRESET "veryfast" /*配置參数
* 使用默认參数,在这里使用了zerolatency的选项,使用这个选项之后,就不会有
* delayed_frames,假设你使用不是这个的话,还须要在编码完毕之后得到缓存的
* 编码帧
*/
#define ENCODER_TUNE "zerolatency"
#define ENCODER_PROFILE "baseline"
#define ENCODER_COLORSPACE X264_CSP_I420 typedef struct my_x264_encoder{
x264_param_t * x264_parameter;
char parameter_preset[20];
char parameter_tune[20];
char parameter_profile[20];
x264_t * x264_encoder;
x264_picture_t * yuv420p_picture;
long colorspace;
unsigned char *yuv;
x264_nal_t * nal;
} my_x264_encoder; char *read_filename="yuv420p.yuv";
char *write_filename="encode.h264"; int main(int argc ,char **argv)
{
int ret;
int fd_read,fd_write;
my_x264_encoder * encoder = (my_x264_encoder *)malloc(sizeof(my_x264_encoder));
if(!encoder){
printf("cannot malloc my_x264_encoder !\n");
exit(EXIT_FAILURE);
}
CLEAR(*encoder); /****************************************************************************
* Advanced parameter handling functions
****************************************************************************/ /* These functions expose the full power of x264's preset-tune-profile system for
* easy adjustment of large numbers //free(encoder->yuv420p_picture);of internal parameters.
*
* In order to replicate x264CLI's option handling, these functions MUST be called
* in the following order:
* 1) x264_param_default_preset
* 2) Custom user options (via param_parse or directly assigned variables)
* 3) x264_param_apply_fastfirstpass
* 4) x264_param_apply_profile
*
* Additionally, x264CLI does not apply step 3 if the preset chosen is "placebo"
* or --slow-firstpass is set. */
strcpy(encoder->parameter_preset,ENCODER_PRESET);
strcpy(encoder->parameter_tune,ENCODER_TUNE); encoder->x264_parameter = (x264_param_t *)malloc(sizeof(x264_param_t));
if(!encoder->x264_parameter){
printf("malloc x264_parameter error!\n");
exit(EXIT_FAILURE);
} /*初始化编码器*/
CLEAR(*(encoder->x264_parameter));
x264_param_default(encoder->x264_parameter); if((ret = x264_param_default_preset(encoder->x264_parameter,encoder->parameter_preset,encoder->parameter_tune))<0){
printf("x264_param_default_preset error!\n");
exit(EXIT_FAILURE);
} /*cpuFlags 去空缓冲区继续使用不死锁保证*/
encoder->x264_parameter->i_threads =X264_SYNC_LOOKAHEAD_AUTO;
/*视频选项*/
encoder->x264_parameter->i_width =IMAGE_WIDTH;//要编码的图像的宽度
encoder->x264_parameter->i_height =IMAGE_HEIGHT;//要编码的图像的高度
encoder->x264_parameter->i_frame_total =0;//要编码的总帧数,不知道用0
encoder->x264_parameter->i_keyint_max =25;
/*流參数*/
encoder->x264_parameter->i_bframe =5;
encoder->x264_parameter->b_open_gop =0;
encoder->x264_parameter->i_bframe_pyramid=0;
encoder->x264_parameter->i_bframe_adaptive=X264_B_ADAPT_TRELLIS; /*log參数,不须要打印编码信息时直接凝视掉*/
encoder->x264_parameter->i_log_level =X264_LOG_DEBUG; encoder->x264_parameter->i_fps_den =1;//码率分母
encoder->x264_parameter->i_fps_num =25;//码率分子
encoder->x264_parameter->b_intra_refresh =1;
encoder->x264_parameter->b_annexb =1; strcpy(encoder->parameter_profile,ENCODER_PROFILE);
if((ret=x264_param_apply_profile(encoder->x264_parameter,encoder->parameter_profile))<0){
printf("x264_param_apply_profile error!\n");
exit(EXIT_FAILURE);
}
/*打开编码器*/
encoder->x264_encoder = x264_encoder_open(encoder->x264_parameter);
encoder->colorspace = ENCODER_COLORSPACE; /*初始化pic*/
encoder->yuv420p_picture = (x264_picture_t *)malloc(sizeof(x264_picture_t ));
if(!encoder->yuv420p_picture){
printf("malloc encoder->yuv420p_picture error!\n");
exit(EXIT_FAILURE);
}
if((ret = x264_picture_alloc(encoder->yuv420p_picture,encoder->colorspace,IMAGE_WIDTH,IMAGE_HEIGHT))<0){
printf("ret=%d\n",ret);
printf("x264_picture_alloc error!\n");
exit(EXIT_FAILURE);
} encoder->yuv420p_picture->img.i_csp = encoder->colorspace;
encoder->yuv420p_picture->img.i_plane = 3;
encoder->yuv420p_picture->i_type = X264_TYPE_AUTO; /*申请YUV buffer*/
encoder->yuv = (uint8_t *)malloc(IMAGE_WIDTH*IMAGE_HEIGHT*3/2);
if(!encoder->yuv){
printf("malloc yuv error!\n");
exit(EXIT_FAILURE);
}
CLEAR(*(encoder->yuv));
encoder->yuv420p_picture->img.plane[0] = encoder->yuv;
encoder->yuv420p_picture->img.plane[1] = encoder->yuv+IMAGE_WIDTH*IMAGE_HEIGHT;
encoder->yuv420p_picture->img.plane[2] = encoder->yuv+IMAGE_WIDTH*IMAGE_HEIGHT+IMAGE_WIDTH*IMAGE_HEIGHT/4; if((fd_read = open(read_filename,O_RDONLY))<0){
printf("cannot open input file!\n");
exit(EXIT_FAILURE);
} if((fd_write = open(write_filename,O_WRONLY | O_APPEND | O_CREAT,0777))<0){
printf("cannot open output file!\n");
exit(EXIT_FAILURE);
} int n_nal = 0;
x264_picture_t pic_out;
x264_nal_t *my_nal;
encoder->nal = (x264_nal_t *)malloc(sizeof(x264_nal_t ));
if(!encoder->nal){
printf("malloc x264_nal_t error!\n");
exit(EXIT_FAILURE);
}
CLEAR(*(encoder->nal)); /*编码*/
while(read(fd_read,encoder->yuv,IMAGE_WIDTH*IMAGE_HEIGHT*3/2)>0){
encoder->yuv420p_picture->i_pts++;
if((ret = x264_encoder_encode(encoder->x264_encoder,&encoder->nal,&n_nal,encoder->yuv420p_picture,&pic_out))<0){
printf("x264_encoder_encode error!\n");
exit(EXIT_FAILURE);
} for(my_nal = encoder->nal; my_nal<encoder->nal+n_nal; ++my_nal){
write(fd_write,my_nal->p_payload,my_nal->i_payload);
}
} free(encoder->yuv);
free(encoder->yuv420p_picture);
free(encoder->x264_parameter);
x264_encoder_close(encoder->x264_encoder);
free(encoder);
close(fd_read);
close(fd_write); return 0;
}

/*File : decode_h264.c
*Auth : sjin
*Date : 20141115
*Mail : 413977243@qq.com
*/ /*将h264解码为yuv文件*/ #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h> #define DECODED_OUTPUT_FORMAT AV_PIX_FMT_YUV420P
#define INPUT_FILE_NAME "encode.h264"
#define OUTPUT_FILE_NAME "decode.yuv"
/*h264文件的宽度和高度,必须和实际的宽度和高度一致
*否则将出错
* */
#define IMAGE_WIDTH 176
#define IMAGE_HEIGHT 144 void error_handle(const char *errorInfo )
{
printf("%s error!\n",errorInfo);
exit(EXIT_FAILURE);
} int main(int argc,char ** argv)
{
int write_fd,ret,videoStream;
AVFormatContext * formatContext=NULL;
AVCodec * codec;
AVCodecContext * codecContext;
AVFrame * decodedFrame;
AVPacket packet;
uint8_t *decodedBuffer;
unsigned int decodedBufferSize;
int finishedFrame; //初始化环境
av_register_all(); write_fd = open(OUTPUT_FILE_NAME,O_RDWR | O_CREAT,0666);
if(write_fd<0){
perror("open");
exit(1);
} ret = avformat_open_input(&formatContext, INPUT_FILE_NAME, NULL,NULL);
if(ret<0)
error_handle("avformat_open_input error"); ret = avformat_find_stream_info(formatContext,NULL);
if(ret<0)
error_handle("av_find_stream_info"); //打印输入文件的具体信息
av_dump_format(formatContext,0,INPUT_FILE_NAME,0); videoStream = 0;
codecContext = formatContext->streams[videoStream]->codec; codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if(codec == NULL)
error_handle("avcodec_find_decoder error!\n"); ret = avcodec_open2(codecContext,codec,NULL);
if(ret<0)
error_handle("avcodec_open2"); //分配保存视频帧的空间
decodedFrame = avcodec_alloc_frame();
if(!decodedFrame)
error_handle("avcodec_alloc_frame!"); //分配解码后视频帧的空间
decodedBufferSize = avpicture_get_size(DECODED_OUTPUT_FORMAT,IMAGE_WIDTH,IMAGE_HEIGHT);
decodedBuffer = (uint8_t *)malloc(decodedBufferSize);
if(!decodedBuffer)
error_handle("malloc decodedBuffer error!"); av_init_packet(&packet);
while(av_read_frame(formatContext,&packet)>=0){
ret = avcodec_decode_video2(codecContext,decodedFrame,&finishedFrame,&packet);
if(ret<0)
error_handle("avcodec_decode_video2 error!");
if(finishedFrame){
avpicture_layout((AVPicture*)decodedFrame,DECODED_OUTPUT_FORMAT,IMAGE_WIDTH,IMAGE_HEIGHT,decodedBuffer,decodedBufferSize);
ret = write(write_fd,decodedBuffer,decodedBufferSize);
if(ret<0)
error_handle("write yuv stream error!");
} av_free_packet(&packet);
} /*防止视频解码完毕后丢帧的情况*/
while(1){
packet.data = NULL;
packet.size = 0;
ret = avcodec_decode_video2(codecContext,decodedFrame,&finishedFrame,&packet);
if(ret<=0 && (finishedFrame<=0))
break;
if(finishedFrame){
avpicture_layout((AVPicture*)decodedFrame,DECODED_OUTPUT_FORMAT,IMAGE_WIDTH,IMAGE_HEIGHT,decodedBuffer,decodedBufferSize);
ret = write(write_fd,decodedBuffer,decodedBufferSize);
if(ret<0)
error_handle("write yuv stream error!");
} av_free_packet(&packet);
} avformat_close_input(&formatContext);
free(decodedBuffer);
av_free(decodedFrame);
avcodec_close(codecContext); return 0;
}

Makefile:

# use pkg-config for getting CFLAGS and LDLIBS
FFMPEG_LIBS= libavdevice \
libavformat \
libavfilter \
libavcodec \
libswresample \
libswscale \
libavutil \ CFLAGS += -Wall -O2 -g
CFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS)
LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS) EXAMPLES= decode_h264 yuvTO264 OBJS=$(addsuffix .o,$(EXAMPLES)) # the following examples make explicit use of the math library
LDLIBS += -lx264 -m32 -pthread -lm -ldl .phony:all clean all: $(OBJS) $(EXAMPLES) clean:
rm $(EXAMPLES) $(OBJS)

參考资料:

參考资料
1、http://blog.csdn.net/liushu1231/article/details/9203239
2、http://www.cnblogs.com/fojian/archive/2012/09/01/2666627.html
3、http://stackoverflow.com/questions/2940671/how-does-one-encode-a-series-of-images-into-h264-using-the-x264-c-api
4、http://blog.yikuyiku.com/?p=3486

live555搭建的rtspserver发送当前屏幕(x264)

使用X264编码yuv格式的视频帧使用ffmpeg解码h264视频帧的更多相关文章

  1. (转)FFMPEG解码H264拼帧简解

    http://blog.csdn.net/ikevin/article/details/7649095 H264的I帧通常 0x00 0x00 0x00 0x01 0x67 开始,到下一个帧头开始之前 ...

  2. iPhone调用ffmpeg2.0.2解码h264视频的示例代码

    iPhone调用ffmpeg2.0.2解码h264视频的示例代码 h264demo.zip 关于怎么在MAC下编译iOS下的ffmpeg请看 编译最新ffmpeg2.0.1(ffmpeg2.0.2)到 ...

  3. Android 音视频深入 九 FFmpeg解码视频生成yuv文件(附源码下载)

    项目地址,求star https://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(MP4%E8 ...

  4. ffmpeg解码音视频过程(附代码)

    0. 引言 最近一直在使用和学习ffmpeg. 工作中需要拉流解码, 获取音频和视频数据. 这些都是使用ffmpeg处理. 因为对ffmpeg接触不多, 用的不深, 在使用的过程中经常遇到不太懂的地方 ...

  5. Android 音视频深入 三 MP4解码播放视频 (附源码下载)

    本篇项目地址,名字是媒体解码MediaCodec,MediaExtractor,求starhttps://github.com/979451341/Audio-and-video-learning-m ...

  6. YUV格式具体解释

    YUV是指亮度參量和色度參量分开表示的像素格式,而这样分开的优点就是不但能够避免相互干扰,还能够减少色度的採样率而不会对图像质量影响太大.YUV是一个比較笼统地说法,针对它的详细排列方式,能够分为非常 ...

  7. YUV格式全解

    YUV是指亮度参量和色度参量分开表示的像素格式,而这样分开的好处就是不但可以避免相互干扰,还可以降低色度的采样率而不会对图像质量影响太大.YUV是一个比较笼统地说法,针对它的具体排列方式,可以分为很多 ...

  8. YUV格式详解【转】

    转自:http://blog.csdn.net/searchsun/article/details/2443867 [-] YUV格式解析1播放器project2 YUV 采样 表面定义 YUV格式解 ...

  9. 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码

    ffmpeg开源库,实现将bmp格式的图片编码成x264文件,并将编码好的H264文件解码保存为BMP文件. 实现将视频文件yuv格式保存的图片格式的測试,图像格式png,jpg, gif等等測试均O ...

随机推荐

  1. STM32M CUBE实现printf打印调试信息以及实现单字节接收

    在写单片机程序时我们一般喜欢使用printf来通过串口打印调试信息,但这个函数是不能够直接使用的.必须做点对库函数的修改. 具体project下载地址: http://download.csdn.ne ...

  2. 移动M站建设

    电商总结(五)移动M站建设   最近在一直在搞M站,也就是移动web站点.由于是第一次,也遇到了很多问题,所以把最近了解到的东西总结总结.聊一聊什么是移动M站,它有啥作用和优势. 也有人会问,M站和A ...

  3. poj3662(二分+最短路)

    题目连接:http://poj.org/problem?id=3662 题意:有n个节点p条无向边,现在可以选择其中的任意K条免费,则花费为除了k条边后权值最大的一个,求最小花费多少. 分析:二分枚举 ...

  4. myeclipse10.7皴,出口解决war包时报“SECURITY ALERT: INTEGERITY CHECK ERROR”

    一.操作系统的环境是win7,64bit和32bit的操作系统我试过都OK 依照网上一些Crack破解程序步骤操作就能够完毕破解过程, 也能够到我的CSDN资源里下载文件包 myeclipse10.7 ...

  5. cisco san交换机配置

    1.配置交换机的管理地址switch(config)# interface mgmt 0 switch(config-if)# ip adress 192.168.100.108 255.255.25 ...

  6. eval、json.parse()的介绍和使用注意点

    原文:eval.json.parse()的介绍和使用注意点 eval和json.parse的使用 eval:来源于官网 定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScri ...

  7. c#事件委托

    转载地址:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1703368.html    从序言中,大家应该对委托和事件的重要性有点了解了吧, ...

  8. Codeforces Round #253 DIV1 C 馋

    http://codeforces.com/contest/442/problem/C 题意非常easy,基本上肯定有坑坑洼洼的样子.看题目案例,从第三个跟第二个没有凹的案例来看的话,多写几个以及多画 ...

  9. python学习1(小白记录)

    python创建cocos2d-x项目注意点1. 2.7.5版本号的.配置好环境变量之后.要切换到tools文件夹下.直接运行 python create_project.py ..........这 ...

  10. c#程序内存分配

    c#程序内存分配 进程可使用内存数就是操作系统给进程分配的最大地址,一般的32位操作系统提供给用户地址最大都是3g(操作系统自己保留1g),windows由于商业目的,对于个人用户只提供了2g地址,要 ...