前面一篇博客介绍在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. Maven聚合

    <project xmlns="http://maven.apache.org/POM/4.0.0"  xmlns:xsi="http://www.w3.org/2 ...

  2. 明晚8点,捷微团队QQ群公开课,解说jeewx2.0版本号maven环境的搭建入门!

    2014-08-13号晚8点,捷微团队QQ群公开课,解说jeewx2.0版本号maven环境的搭建入门! 讲师:刘强(团队成员) QQ群:287090836 (JAVA版本号微信开源项目) http: ...

  3. iOS 史上最全的图片压缩方法集合

    做上传图片功能,特别是类似于微信,QQ里面,公布9张图片, 少不了碰到一个问题,就是图片压缩问题,当然我也遇到了. 我研究了这个问题,发现网上普遍的方法是例如以下 //压缩图片质量 +(UIImage ...

  4. Android - JNI静态(static)载入OpenCV

    JNI静态(static)载入OpenCV 本文地址: http://blog.csdn.net/caroline_wendy 步骤: 1. 准备OpenCV-Android库 复制OpenCV的sd ...

  5. 我为什么要创建帮创业者找合伙人的缘创派(ycpai.com)?

    我为什么要创建帮助创业者找合伙人的缘创派(ycpai.com)? 在我发出第一条离开CSDN出来创业的微博后,感谢各位朋友的鼓励.很多朋友问我一些问题,我在这里一并回答,并简单阐述一下我的理念. 问: ...

  6. The tempfile module

    The tempfile module The tempfile module This module allows you to quickly come up with unique names ...

  7. Oracle GoldenGate for Oracle 11g to PostgreSQL 9.2.4 Configuration

    Installing and setting up Oracle GoldenGate connecting to an Oracle database Also please make sure t ...

  8. VSTO学习笔记(五)批量编辑Excel 2010 x64

    原文:VSTO学习笔记(五)批量编辑Excel 2010 x64 近期因为工作的需要,经常要批量处理大量的Excel文件,如果纯手工一个个修改,非常的麻烦,于是写了这么一个帮助类,希望能对你有所帮助. ...

  9. Codeforces Round #296 (Div. 1) E. Triangles 3000

    http://codeforces.com/contest/528/problem/E 先来吐槽一下,一直没机会进div 1, 马力不如当年, 这场题目都不是非常难,div 2 四道题都是水题! 题目 ...

  10. .Net程序猿乐Android开发---(4)注册页面布局

    接下来我们介绍的登陆页面布局,在本节中,我们看一下注册页面布局,页面布局大同小异,来一起熟悉下基本控件的使用方法. 效果图: 1.加入注冊页面 右键选中layout目录,加入注冊页面.例如以下图 点击 ...