X264编码实现

H264
  H264的官方测试源码,由德国hhi研究所负责开发。
特点:实现了264所有的特性,由于是官方的测试源码,所以学术研究的算法都是在JM基础上实现并和JM进行比较。但其程序结构冗长,
只考虑引入各种新特性以提高编码性能,忽视了编码复杂度,其编码复杂度极高,不宜实用。
X264
  网上自由组织联合开发的兼容264标准码流的编码器,创始人是一个法国人。X264在网上的口碑极佳。
特点:注重实用。和JM相比,在不明显降低编码性能的前提下,努力降低编码的计算复杂度,故X264摈弃了264中一些对编码性能贡献
微笑但计算复杂度极高的新特性,如多参考帧、帧间预测中不必要的块模式、CABAC等。
编码格式输出:
  总的来说H264的码流的打包方式有两种,一种为annex-b byte stream format的格式,这个是绝大部分编码器的默认输出格式,就是
每个帧的开头的3~4个字节是H264的start_code,0x00000001或者0x000001。
另一种是原始的NAL打包格式,就是开始的若干字节(1,2,4字节)是NAL的长度,而不是start_code,此时必须借助某个全局的数据
来获得编码器的profile,level,PPS,SPS等信息才可以解码。

h264encoder.h

/**
*
* Created on: Dec 10, 2010
*  Author: Henry.wen
*/
#ifndef _H264ENCODER_H
#define _H264ENCODER_H

#include <stdint.h>
#include <inttypes.h>

extern "C"
{
#include "matroska.h"
}

void save_image(const char* filePath, const void* bufferBase, int width, int height);

int encoder_init(const char* filePath, int width, int height);

int encoder_frame(const void* frame);

void encoder_close();

#endif

 h264encoder.cpp

extern "C"
{
#include <matroska.h>
}

#include <skia/core/SkBitmap.h>
#include <skia/images/SkImageEncoder.h>

#include <android_runtime/AndroidRuntime.h>

#include "h264encoder.h"

#ifndef X264_MAX
#define X264_MAX( a, b ) ( (a) < (b) ? (b) : (a))
#endif

x264_param_t    g_param;
x264_picture_t  g_pic_in;
x264_picture_t  g_pic_out;
x264_t         *g_encoder  = NULL;
int             g_width    = 0;
int             g_height   = 0;
FILE*           g_file     = 0;
int64_t         g_pts      = 0;
int             g_flagInit = 0;

using namespace android;
static Mutex sg_mutexLock;

#ifndef LOGI
#define LOGI(...) ((void)__android_log_print("H264ENCODE",  MOBIHEARTCAMERA_LOG_TAG, __VA_ARGS__))
#endif

void save_image(const char* filePath, const void* bufferBase, int width, int height)
{
	Mutex::Autolock lock(sg_mutexLock);
	SkBitmap b;
	b.setConfig(SkBitmap::kARGB_8888_Config, width, height);
	b.setPixels((void*)bufferBase);
	SkImageEncoder::EncodeFile(filePath, b, SkImageEncoder::kJPEG_Type, SkImageEncoder::kDefaultQuality);
}

int encoder_init(const char* filePath, int width, int height)
{
	LOGI("encoder_init ============begin");
	if(g_flagInit != 0)
	{
		LOGI("encoder_init have encoding!");
		return 0;
	}

	Mutex::Autolock lock(sg_mutexLock);

	x264_param_default_preset(&g_param, "fast", "zerolatency");

	g_param.i_width = width;
	g_param.i_height = height;
	g_param.i_fps_num = 25;
	g_param.i_fps_den = 1;

	g_width = width;
	g_height = height;

	g_param.i_keyint_max = 25;
	g_param.b_intra_refresh = 1;
	g_param.b_annexb = 1;

	x264_param_apply_profile(&g_param, x264_profile_names[0]);

	g_encoder = x264_encoder_open(&g_param);
	if(g_encoder == 0)
	{
		LOGI("encoder_init open encoder fail!");
		return -1;
	}
	g_param.rc.i_lookahead = 0;

	if( 0 != x264_picture_alloc(&g_pic_in, X264_CSP_I420, width, height))//X264_CSP_I420
	{
		LOGI("encoder_init alloc picture fail!");
		x264_encoder_close(g_encoder);
		g_encoder = 0;
		return -1;
	}

	g_file     = fopen(filePath, "w+b");
	if(g_file == NULL)
	{
		x264_encoder_close(g_encoder);
		g_encoder = 0;
		return -1;
	}

	g_flagInit = 1;
	g_pts      = 0;

	return 0;
}

int encoder_frame(const void* frame)
{
	LOGI("encoder_frame ============begin");
	if(g_flagInit > 0)
	{
		Mutex::Autolock lock(sg_mutexLock);

		g_pic_in.img.plane[0] = (uint8_t*)frame;

		uint8_t* tmpBuffer_uv = g_pic_in.img.plane[0] + g_width * g_height;
		uint8_t* tmpBuffer_u = g_pic_in.img.plane[1];
		uint8_t* tmpBuffer_v = g_pic_in.img.plane[2];

		int index = 0;
		for(int j = 0, nCount = (g_height >> 1) * g_width; j < nCount; j +=2)
		{
			*(tmpBuffer_u + index) = *(tmpBuffer_uv + index);
			*(tmpBuffer_v + index + 1) = *(tmpBuffer_uv + index + 1);

			++index;
		}

		int nnal;
		x264_nal_t *nals;

		g_pic_in.i_pts = g_pts;
		g_pic_in.i_type = X264_TYPE_AUTO;

		int ret = x264_encoder_encode(g_encoder, &nals, &nnal, &g_pic_in, &g_pic_out);
		if( ret < 0)
		{
			LOGI("encoder_frame encode frame fail, ret = %d", ret);
			return 0;
		}
		++g_pts;

		fwrite(nals[0].p_payload, ret, 1, g_file );
	}
	LOGI("encoder_frame ============end");
	return 0;
}

void encoder_close()
{
	LOGI("encoder_close ============begin");
	Mutex::Autolock lock(sg_mutexLock);

	if(g_encoder)
		x264_encoder_close(g_encoder);

	g_encoder = 0;

	if(g_file)
		fclose(g_file);

	g_file = 0;

	g_flagInit = 0;
	LOGI("encoder_close ============end");
}

  

 

时间: 2024-11-10 15:56:58

X264编码实现的相关文章

x264编码延时研究

研究了一下x264编码延时. 方法是加log在x264.c static int encode( x264_param_t *param, cli_opt_t *opt ) { ... i_frame_size = encode_frame( h, opt->hout, &pic, &last_dts ); if( i_frame_size == 0)   // delay frames fprintf( stderr, "output zero %d\n", i

视频x264编码浅析

声明 x264_param_t 结构体变量: x264_param_t params; x264_param_default_preset(&params, "ultrafast", "zerolatency");//优化编码延迟? 变量参数编码前赋值: params.i_csp = (csp == 17) ? X264_CSP_NV12 : csp;//编码比特流的CSP,仅支持i420,色彩空间设置 #ifdef SQUARE_AND_ROTATE pa

X264编码流程详解(转)

http://blog.csdn.net/xingyu19871124/article/details/7671634 对H.264编码标准一直停留在理解原理的基础上,对于一个实际投入使用的编码器是如何构建起来一直感觉很神秘,于是决定在理解理论的基础上潜心于编码器实现框架.关于开源的H264编码器有很多,JMVC,T264.X264,这里选择X264,因为网上关于X264源码分析资源很多.X264编码器是一个开源的经过优化的高性能H.264编码器,目前最新的源码在本人的I5处理器的PC机上,编码

WebRTC VideoEngine超详细教程(三)——集成X264编码和ffmpeg解码

总述 在前一篇文章中,讲解了如何将OPENH264编解码器集成到WebRTC中,但是OPENH264只能编码baseline的H264视频,而且就编码质量而言,还是X264最好,本文就来讲解一下如何将X264编码器集成到WebRTC中,为了实现解码,同时要用到ffmpeg.总体流程和之前一样,分为重新封装编解码器和注册调用两大步骤,注册调用这一步没有任何不同,主要是重新封装这一步骤有较大区别. 重新封装X264编码功能 首先当然还是要下载X264源码编译出相应的库以供调用.在windows下使用

x264 编码数配置

记录项目中用到一组x264快速编码参数配置,具体如下: param->i_frame_reference = 1; param->i_scenecut_threshold = 0; param->b_deblocking_filter = 0; param->b_cabac = 0; param->i_bframe = 0; param->analyse.intra = 0; param->analyse.inter = 0; param->analyse.

用X264编码以后的H264数据

输入的数据准备好了,编码后的数据都在x264_nal_t的数组.我这里设置的参数是Baseline Profile,所以编码后没有B帧,将编码后的数据保存分析后发现,第一次编码的时候会有4个NAl,分别是SPS.PPS.SEI.I帧,也即分别是00 00 00 01 67. 00 00 00 01 68. 00 00  01 06.00 00 01 65开头的四个数据段,这里注意的是SEI和I帧的开头貌似X264中就是00 00 01的起始头了,应该是和源码中这样写的关系,不过没有什么大碍,就是

ffmpeg,X264编码结果I帧QP比P帧还大

enc_ctx->profile =FF_PROFILE_H264_MAIN ; enc_ctx->time_base.den = 24; enc_ctx->time_base.num = 1; enc_ctx->gop_size = 8; /* emit one intra frame every twelve frames at most */ enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P; enc_ctx->max_b_frames

(转)x264 编码流程

转自:http://alphamailpost.blog.163.com/blog/static/20111808120128111160728/ http://www.usr.cc/thread-52674-1-1.html Main函数中包含三个函数:Init,Encode,Fini,分别用来初始化,编码和编码后内存处理. Init: I(1)X264_param_default: 参数初始化,包括:CPU,视频参数,编码参数,码率控制参数,日志,分析参数和量化参数等.需要注意的是: par

几组不错的X264自定义编码&lt;转&gt;

转帖地址:http://tieba.baidu.com/p/4201033507 一般直播时使用A设定即可.你尝试设置并找出你最满意的设定 A为最需最低CPU资源,E为最高. A8x8dct=1 aq-mode=2 bframes=1 chroma-qp-offset=1 colormatrix=smpte170m deblock=0:0 direct=auto ipratio=1.41 keyint=240 level=3.1 me=hex merange=16 min-keyint=auto