1. 程式人生 > >h.264編碼庫x264例項

h.264編碼庫x264例項

x264是一個開源的H.264編碼庫。本文介紹其在x86 linux的編譯方法,並給出例項。

一、編譯

# ./configure;make;make install

x264官方下載:http://www.videolan.org/developers/x264.html。下載壓縮包名為:last_x264.tar.bz2。解壓得到的檔名為x264-snapshot-xxxx。編譯命令如下:

$ ./configure  --prefix=/home/latelee/bin/x264 --enable-static
$ make
$ make install

二、例項

下面給出使用的示例。

/**
x264庫編碼要使用以下庫
-lpthread -ldl
要求標頭檔案:stdint.h
ffprobe資訊:
Input #0, h264, from 'test.h264':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: h264 (High), yuv420p, 176x144, 25 fps, 25 tbr, 1200k tbn
, 50 tbc

*/

#include <stdio.h>
#include <stdlib.h>

#include <stdint.h> // for uint8_t in x264.h

#include "x264.h"

int x264_encode(const char* infile, int width, int height, int type, const char* outfile)
{
	FILE *fp_src = NULL;
	FILE *fp_dst = NULL;
    unsigned int luma_size = 0;
    unsigned int chroma_size = 0;
    int i_nal = 0;
    int i_frame = 0;
    unsigned int i_frame_size = 0;

    int csp = type;//X264_CSP_I420;
    x264_nal_t* nal = NULL;
    x264_t* handle = NULL;
    x264_picture_t* pic_in = NULL;
    x264_picture_t* pic_out = NULL;
    x264_param_t param;

    fp_src = fopen(infile, "rb");
    fp_dst = fopen(outfile, "wb");
    if(fp_src==NULL || fp_dst==NULL)
    {
        perror("Error open yuv files:");
        return -1;
    }

    x264_param_default(¶m);

    param.i_width  = width;
    param.i_height = height;
    /*
    //Param
    param.i_log_level  = X264_LOG_DEBUG;
    param.i_threads  = X264_SYNC_LOOKAHEAD_AUTO;
    param.i_frame_total = 0;
    param.i_keyint_max = 10;
    param.i_bframe  = 5;
    param.b_open_gop  = 0;
    param.i_bframe_pyramid = 0;
    param.rc.i_qp_constant=0;
    param.rc.i_qp_max=0;
    param.rc.i_qp_min=0;
    param.i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
    param.i_fps_den  = 1;
    param.i_fps_num  = 25;
    param.i_timebase_den = param.i_fps_num;
    param.i_timebase_num = param.i_fps_den;
    */
    param.i_csp = csp;
    param.b_repeat_headers = 1;
    param.b_annexb = 1;

    // profile: high x264_profile_names定義見x264.h
    x264_param_apply_profile(¶m, x264_profile_names[2]);

    pic_in = (x264_picture_t*)malloc(sizeof(x264_picture_t));
    if (pic_in == NULL)
    {
        goto out;
    }
    pic_out = (x264_picture_t*)malloc(sizeof(x264_picture_t));
    if (pic_out == NULL)
    {
        goto out;
    }
    x264_picture_init(pic_out);
    x264_picture_alloc(pic_in, csp, param.i_width, param.i_height);

    handle = x264_encoder_open(¶m);

    // 計算有多少幀
    luma_size = param.i_width * param.i_height;
    fseek(fp_src, 0, SEEK_END);
    switch (csp)
    {
        case X264_CSP_I444:
            i_frame = ftell(fp_src) / (luma_size*3);
            chroma_size = luma_size;
            break;
        case X264_CSP_I420:
            i_frame = ftell(fp_src) / (luma_size*3/2);
            chroma_size = luma_size / 4;
            break;
        default:
            printf("Colorspace Not Support.\n");
            goto out;
    }
    fseek(fp_src, 0, SEEK_SET);

    printf("framecnt: %d, y: %d u: %d\n", i_frame, luma_size, chroma_size);

    // 編碼
    for (int i = 0; i < i_frame; i++)
    {
        switch(csp)
        {
        case X264_CSP_I444:
        case X264_CSP_I420:
            i_frame_size = fread(pic_in->img.plane[0], 1, luma_size, fp_src);
            if (i_frame_size != luma_size)
            {
                printf("read luma failed %d.\n", i_frame_size);
                break;
            }
            i_frame_size = fread(pic_in->img.plane[1], 1, chroma_size, fp_src);
            if (i_frame_size != chroma_size)
            {
                printf("read chroma1 failed %d.\n", i_frame_size);
                break;
            }
            i_frame_size = fread(pic_in->img.plane[2], 1, chroma_size, fp_src);
            if (i_frame_size != chroma_size)
            {
                printf("read chrome2 failed %d.\n", i_frame_size);
                break;
            }
            break;
        default:
            printf("Colorspace Not Support.\n");
            return -1;
        }
        pic_in->i_pts = i;

        i_frame_size = x264_encoder_encode(handle, &nal, &i_nal, pic_in, pic_out);
        printf("encode frame: %5d framesize: %d nal: %d\n", i+1, i_frame_size, i_nal);
        if (i_frame_size < 0)
        {
            printf("Error encode frame: %d.\n", i+1);
            goto out;
        }
        #if 01
        else if (i_frame_size)
        {
            if(!fwrite(nal->p_payload, 1, i_frame_size, fp_dst))
                goto out;
        }
        #endif
        // 另一種做法
        #if 0
        // i_nal有可能為0,有可能多於1
        for (int j = 0; j < i_nal; j++)
        {
            fwrite(nal[j].p_payload, 1, nal[j].i_payload, fp_dst);
        }
        #endif
    }

    //flush encoder
    while(x264_encoder_delayed_frames(handle))
    //while(1)
    {
        static int cnt = 1;
        i_frame_size = x264_encoder_encode(handle, &nal, &i_nal, NULL, pic_out);
        printf("flush frame: %d framesize: %d nalsize: %d\n", cnt++, i_frame_size, i_nal);
        if(i_frame_size == 0)
        {
            break;
            //goto out;
        }
        #if 01
        else if(i_frame_size)
        {
            if(!fwrite(nal->p_payload, 1, i_frame_size, fp_dst))
                goto out;
        }
        #endif
        // 另一種做法
        #if 0
        // i_nal有可能為0,有可能多於1
        for (int j = 0; j < i_nal; j++)
        {
            fwrite(nal[j].p_payload, 1, nal[j].i_payload, fp_dst);
        }
        #endif
    }

out:
    x264_picture_clean(pic_in);
    if (handle)
    {
        x264_encoder_close(handle);
        handle = NULL;
    }

    if (pic_in)
        free(pic_in);
    if (pic_out)
        free(pic_out);

    fclose(fp_src);
    fclose(fp_dst);

    return 0;
}

使用方法:

x264_encode("../src/suzie_qcif_176x144_yuv420p.yuv", 176, 144, 1, "test.h264");

Makefile如下:

#
# (C) Copyleft 2011~2015
# Late Lee from http://www.latelee.org
# 
# A simple Makefile for *ONE* project(c or/and cpp file) in *ONE*  directory
#
# note: 
# you can put head file(s) in 'include' directory, so it looks 
# a little neat.
#
# usage: $ make
#        $ make debug=y
#
# log
#       2013-05-14 sth about debug...
###############################################################################

# !!!=== cross compile...
CROSS_COMPILE = 

CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar

ARFLAGS = cr
RM = -rm -rf
MAKE = make

CFLAGS := -Wall

#****************************************************************************
# debug can be set to y to include debugging info, or n otherwise
debug          := n

#****************************************************************************

ifeq ($(debug), y)
CFLAGS += -ggdb -rdynamic
else
CFLAGS += -O2 -s
endif

# !!!===
DEFS = 

CFLAGS += $(DEFS)

LDFLAGS := $(LIBS)

# !!!===
INCDIRS := -I./include

# !!!===
CFLAGS += $(INCDIRS)

# !!!===
LDFLAGS += ./lib/libx264.a ./lib/libx265.a -lpthread -ldl

# !!!===
# source file(s), including c file(s) cpp file(s)
# you can also use $(wildcard *.c), etc.
SRC_C   := $(wildcard *.c)
SRC_CPP := $(wildcard *.cpp)

# object file(s)
OBJ_C   := $(patsubst %.c,%.o,$(SRC_C))
OBJ_CPP := $(patsubst %.cpp,%.o,$(SRC_CPP))

# !!!===
# executable file
target = a.out

###############################################################################

all: $(target)

$(target): $(OBJ_C) $(OBJ_CPP)
	@echo "Generating executable file..." $(notdir $(target))
	@$(CXX) $(CFLAGS) $^ -o $(target) $(LDFLAGS)

# make all .c or .cpp
%.o: %.c
	@echo "Compiling: " $(addsuffix .c, $(basename $(notdir 
[email protected]
))) @$(CC) $(CFLAGS) -c $< -o [email protected] %.o: %.cpp @echo "Compiling: " $(addsuffix .cpp, $(basename $(notdir [email protected]))) @$(CXX) $(CFLAGS) -c $< -o [email protected] clean: @echo "Cleaning..." @$(RM) $(target) @$(RM) *.o *.back *~ .PHONY: all clean


李遲 2015.9.14 中午

相關推薦

h.264編碼x264例項

x264是一個開源的H.264編碼庫。本文介紹其在x86 linux的編譯方法,並給出例項。 一、編譯 # ./configure;make;make install x264官方下載:http://www.videolan.org/developers/x264.htm

H.264編碼格式分析

mas rail head nalu 比特流 包括 val slice raw   H.264的重要性不再提了。本文主要記錄一下H.264的編碼格式。H.264官方文檔:https://github.com/jiayayao/DataSheet/tree/master/en

【轉】 H.264編碼原理以及I幀B幀P幀

獨立 像素 疊加 提高 oss 解壓 防止 相同 大小 轉自:http://www.cnblogs.com/herenzhiming/articles/5106178.html 前言 ----------------------- H264是新一代的編碼標準,

為什麼NVIDIA NVENC 硬體H.264編碼器對XD和Horizon如此重要

本文翻譯自Magnar Johnsen的一篇文章,該文章論述了在Citrix XenDesktop和VMware Horizon解決方案中,如果使用了NVIDIA GRID card的NVENC的功能,那麼對於使用3D軟體的使用者來說,無論是效能還是使用者體驗,都有較大的提升。根據個人理解翻譯,如有理解不對的

C++實現RTMP協議傳送H.264編碼及AAC編碼的音視訊直播

  RTMP(Real Time Messaging Protocol)是專門用來傳輸音視訊資料的流媒體協議,最初由Macromedia 公司建立,後來歸Adobe公司所有,是一種私有協議,主要用來聯絡Flash Player和RtmpServer,如FMS, Red5, 

H.264---編碼架構分析

一、編碼架構分析   編碼器有兩條資料通道:前向通道和重建通道。在前向通道中,編碼器的輸入是幀Fn,每幀是以16X16畫素大小的巨集塊單元組成的,每個巨集塊進行幀內或幀間預測編碼。幀間預測的參考幀為前一幀Fn‘,實際上,參考幀的數量可以多達五幀。當前塊減去其預測塊P得到殘差Dn,Dn經過

C++實現RTMP協議傳送H.264編碼及AAC編碼的音視訊

作者HBStream   RTMP(Real Time Messaging Protocol)是專門用來傳輸音視訊資料的流媒體協議,最初由Macromedia 公司建立,後來歸Adobe公司所有,是一種私有協議,主要用來聯絡Flash Player和RtmpServer

H.264編碼原理以及I幀B幀P幀

H264是新一代的編碼標準,以高壓縮高質量和支援多種網路的流媒體傳輸著稱,在編碼方面,我理解的他的理論依據是:參照一段時間內影象的統計結果表明,在相鄰幾幅影象畫面中, 一般有差別的畫素只有10%以內的點,亮度差值變化不超過2%,而色度差值的變化只有1%

H.264編碼原理以及I幀B幀P幀-------淺談

寫在前面:       H264是新一代的編碼標準,以高壓縮高質量和支援多種網路的流媒體傳輸著稱,在編碼方面,我理解的他的理論依據是:參照一段時間內影象的統計結果表明,在相鄰幾幅影象畫面中, 一般有差別的畫素只有10%以內的點,亮度差值變化不超過2%,而色度差值的變化只有

H.264編碼系統幾個比較重要的演算法

H.264編碼系統比較複雜,這裡是它的幾個比較重要的演算法: 1. Configure()函式,用於解析命令列引數,讀取配置檔案,其中,ac表示命令列引數數量,av表示命令列引數。void Configure(int ac, char *av[ ]){……} 2. A

H.264編碼四種畫質級別

H.264編碼四種畫質級別 D1是數字電視系統顯示格式的標準,共分為以下5種規格: D1:480i格式(525i):720×480(水平480線,隔行掃描),和NTSC模擬電視清晰度相同,行頻為15.25kHz,相當於我們所說的4CIF(720×576) D2:480P格式(525p):720×48

H.264編碼原理以及I幀B幀P幀 (2013-01-09 15:24:10)

I幀:幀內編碼幀 ,I幀表示關鍵幀,你可以理解為這一幀畫面的完整保留;解碼時只需要本幀資料就可以完成(因為包含完整畫面) I幀特點: 1.它是一個全幀壓縮編碼幀。它將全幀影象資訊進行JPEG壓縮編碼及傳輸; 2.解碼時僅用I幀的資料就可重構完整影象; 3.I幀描述了影象背景和運動主體的詳情; 4.I幀不需要參

使用GPU加速H.264編碼分析

繼前面的“GPGPU”和“CUDA和OpenCL”的簡介後,接下來分析一個具體的使用案例:是否可以用GPU搭建一個高效能的H.264編解碼伺服器? 設想一個簡單的需求: 把其他編碼的視訊轉換為指定位元速率的H.264;在轉換過程中做一些簡單的處理(例如增刪水印、字幕的

V4L2視訊採集與H.264編碼原始碼大放送:Linux視訊採集與編碼(三)

這幾天的努力也算沒有白費,現在我將貢獻出我的成果,當然程式碼很大一部分都不是我寫的。 V4L2視訊採集我參考了V4L2官方原始碼,H.264編碼我使用了開源編碼庫x264,並參考了網上的一些例子。 但

Android直播開發之旅(2):深度解析H.264編碼原理

 (碼字不易,轉載請申明出處:http://blog.csdn.net/andrexpert/article/details/71774230 ) 前 言     在學習H.264編碼之前,我們先了解一下在視訊直播的過程中,如果Camera採集的YUV影象不做任何處理

新手學習FFmpeg - 呼叫API完成錄屏並進行H.264編碼

Screen Record H.264 目前在網路傳輸視訊/音訊流都一般會採用H.264進行編碼,所以嘗試呼叫FFMPEG API完成Mac錄屏功能,同時編碼為H.264格式。 在上一篇文章中,通過呼叫FFmpeg API完成了Mac平臺下的錄屏功能。在本篇中,對上次的錄屏進行優化,將採集到的視訊流編碼為

H.264/AVC視頻編解碼技術具體解釋】十三、熵編碼算法(3):CAVLC原理

統計 視頻編解碼 高效 png h264 轉化 頻率 遊程編碼 而且 《H.264/AVC視頻編解碼技術具體解釋》視頻教程已經在“CSDN學院”上線。視頻中詳述了H.264的背景、標準協議和實現,並通過一個實戰project的形式對H.264的標準進行解

H.264編碼&硬解碼

firefly rk3288 h.264編解碼 開源硬件 網絡攝像頭 Firefly-RK3288擁有強大的VPU(視像處理器),能夠流暢實現720P和1080P視頻的H.264編解碼;而H.264的壓縮率更高,可以更大程度更小視頻的空間占用。 詳細看視頻演示 1. 演示介紹基於Firef

libx264編碼---YUV影象資料編碼h.264碼流

編譯環境:ubuntu12.04 目標平臺:ARM Cortex A9 交叉編譯器:arm-none-linux-gnueabi-gcc 4.4.1 基本步驟:  一、移植x264庫到ARM板,請看上一篇博文移植x264編碼庫 二、測試:

移植X264編碼到ARM

編譯環境:ubuntu12.04 交叉編譯器:arm-none-linux-gnueabi-gcc 4.4.1 目標板:iTOP4412 (cortex A9)   原始碼準備: X2.64原始碼:http://www.videolan.org/dev