s5pv210中MFC的编码过程

发布者:SparklingMelody最新更新时间:2024-12-18 来源: elecfans关键字:s5pv210  MFC 手机看文章 扫描二维码
随时随地手机看文章

在上一篇《s5pv210中MFC的帧内存格式》中我们知道了MFC编码所需要的格式,现在我们就来看看他的编码过程。首先说一下编码环境,我用的开发板是天嵌的TQ210,运行linux系统,其他开发板差别应该不会很大。 linear mode MFC可以接收两种帧内存格式:linear mode和tile mode,因为tile比较麻烦,我这里就用linear模式来编码。修改MFC_ENC_MAP_FO


在上一篇《s5pv210中MFC的帧内存格式》中我们知道了MFC编码所需要的格式,现在我们就来看看他的编码过程。首先说一下编码环境,我用的开发板是天嵌的TQ210,运行linux系统,其他开发板差别应该不会很大。


linear mode

MFC可以接收两种帧内存格式:linear mode和tile mode,因为tile比较麻烦,我这里就用linear模式来编码。修改MFC_ENC_MAP_FOR_CUR寄存器,让MFC选择linear mode,打开文件drivers/media/video/samsung/mfc50/mfc_opr.c,在676行左右把MEM_STRUCT_TILE_ENC改成MEM_STRUCT_LINEAR。


WRITEL(MEM_STRUCT_LINEAR, MFC_ENC_MAP_FOR_CUR);

保存,重新编译内核。我使用的是TQ210自带的内核,他的MFC默认是使用tile模式的,如果传给他的数据是linear模式的话就会导致花屏。


SsbSipMfcApi

这是三星官方的MFC库函数,我也不清楚在哪里找到的,好像是android源码里的,在linux上也可以使用,需要的话可以在文章最后的github上下载。他里面定义了一些MFC的API,这里我说一下和编码相关的几个函数和结构体。首先是h264的编码参数结构体SSBSIP_MFC_ENC_H264_PARAM,他的定义如下:


复制代码

typedef struct {

    /* common parameters  */

    SSBSIP_MFC_CODEC_TYPE codecType;    /* [IN] codec type */

    int SourceWidth;                    /* [IN] width of video to be encoded */

    int SourceHeight;                   /* [IN] height of video to be encoded */

    int IDRPeriod;                      /* [IN] GOP number(interval of I-frame) */

    int SliceMode;                      /* [IN] Multi slice mode */

    int RandomIntraMBRefresh;           /* [IN] cyclic intra refresh */

    int EnableFRMRateControl;           /* [IN] frame based rate control enable */

    int Bitrate;                        /* [IN] rate control parameter(bit rate) */

    int FrameQp;                        /* [IN] The quantization parameter of the frame */

    int FrameQp_P;                      /* [IN] The quantization parameter of the P frame */

    int QSCodeMax;                      /* [IN] Maximum Quantization value */

    int QSCodeMin;                      /* [IN] Minimum Quantization value */

    int CBRPeriodRf;                    /* [IN] Reaction coefficient parameter for rate control */

    int PadControlOn;                   /* [IN] Enable padding control */

    int LumaPadVal;                     /* [IN] Luma pel value used to fill padding area */

    int CbPadVal;                       /* [IN] CB pel value used to fill padding area */

    int CrPadVal;                       /* [IN] CR pel value used to fill padding area */

    int FrameMap;                       /* [IN] Encoding input mode(tile mode or linear mode) */

    /* H.264 specific parameters */

    int ProfileIDC;                     /* [IN] profile */

    int LevelIDC;                       /* [IN] level */

    int FrameQp_B;                      /* [IN] The quantization parameter of the B frame */

    int FrameRate;                      /* [IN] rate control parameter(frame rate) */

    int SliceArgument;                  /* [IN] MB number or byte number */

    int NumberBFrames;                  /* [IN] The number of consecutive B frame inserted */

    int NumberReferenceFrames;          /* [IN] The number of reference pictures used */

    int NumberRefForPframes;            /* [IN] The number of reference pictures used for encoding P pictures */

    int LoopFilterDisable;              /* [IN] disable the loop filter */

    int LoopFilterAlphaC0Offset;        /* [IN] Alpha & C0 offset for H.264 loop filter */

    int LoopFilterBetaOffset;           /* [IN] Beta offset for H.264 loop filter */

    int SymbolMode;                     /* [IN] The mode of entropy coding(CABAC, CAVLC) */

    int PictureInterlace;               /* [IN] Enables the interlace mode */

    int Transform8x8Mode;               /* [IN] Allow 8x8 transform(This is allowed only for high profile) */

    int EnableMBRateControl;            /* [IN] Enable macroblock-level rate control */

    int DarkDisable;                    /* [IN] Disable adaptive rate control on dark region */

    int SmoothDisable;                  /* [IN] Disable adaptive rate control on smooth region */

    int StaticDisable;                  /* [IN] Disable adaptive rate control on static region */

    int ActivityDisable;                /* [IN] Disable adaptive rate control on high activity region */

} SSBSIP_MFC_ENC_H264_PARAM;

复制代码

这些参数中对码率影响比较大的是FrameQp,取值范围0~51,越小码率越大,取30就差不多了。下面说一下编码相关的函数:


//打开MFC

void *SsbSipMfcEncOpen(void);

//初始化MFC,param就是上面介绍的配置结构体

SSBSIP_MFC_ERROR_CODE SsbSipMfcEncInit(void *openHandle, void *param);

//获取输入缓存

SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetInBuf(void *openHandle, SSBSIP_MFC_ENC_INPUT_INFO *input_info);

//编码

SSBSIP_MFC_ERROR_CODE SsbSipMfcEncExe(void *openHandle);

//获取输出缓存

SSBSIP_MFC_ERROR_CODE SsbSipMfcEncGetOutBuf(void *openHandle, SSBSIP_MFC_ENC_OUTPUT_INFO *output_info);

//关闭MFC

SSBSIP_MFC_ERROR_CODE SsbSipMfcEncClose(void *openHandle);

  


知道了这些后下面我们就可以进行h264编码了。


main()

我这里只说一下大致的过程,在最后我会把源码传到github上去。首先打开两个文件,YUV数据源和保存h264的文件。


fp_yuv = fopen('CITY_704x576_30_orig_01.yuv', 'rb');

fp_strm = fopen('CITY_704x576_30_orig_01.h264', 'wb');

定义param变量,根据视频的参数赋值。


SSBSIP_MFC_ENC_H264_PARAM *param;

param = (SSBSIP_MFC_ENC_H264_PARAM*)malloc(sizeof(SSBSIP_MFC_ENC_H264_PARAM));

memset(param, 0 , sizeof(SSBSIP_MFC_ENC_H264_PARAM));

param->SourceWidth=704;

param->SourceHeight=576;

param->FrameQp=30;

//等等。。。

打开MFC,并用param初始化。


hOpen = SsbSipMfcEncOpen();

SsbSipMfcEncInit(hOpen, param);

获取输入缓存地址,以及h264文件头。


SSBSIP_MFC_ENC_INPUT_INFO input_info;

SSBSIP_MFC_ENC_OUTPUT_INFO output_info;

//获取输入缓存地址

SsbSipMfcEncGetInBuf(hOpen, &input_info);

//获取视频文件头

SsbSipMfcEncGetOutBuf(hOpen, &output_info);

//把文件头写入h264文件

fwrite(output_info.StrmVirAddr, 1, output_info.headerSize, fp_strm);

下面就是把视频一帧一帧的读取,编码,写入文件的过程了。


//读取一帧的Y分量,保存到MFC的输入缓存中。

fread(input_info.YVirAddr, 1, 704 * 576, fp_yuv);

//UV分量,保存到临时数组中,要转换成NV12格式

fread(CbCrBuf, 1, (704 * 576) >> 1, fp_yuv);

// convert YV12 -> NV12

p_nv12 = (char *)input_info.CVirAddr;

p_cb = CbCrBuf;

p_cr = CbCrBuf;

p_cr += ((704 * 576) >> 2);

for(i = 0; i < (704 * 576) >> 2; i++){

    *p_nv12 = *p_cb;

    p_nv12++;

    *p_nv12 = *p_cr;

    p_nv12++;

    p_cb++;

    p_cr++;

}

//编码

SsbSipMfcEncExe(hOpen);

//获取输出缓存地址,和大小

SsbSipMfcEncGetOutBuf(hOpen, &output_info);

//写入h264文件

fwrite(output_info.StrmVirAddr, 1, output_info.dataSize, fp_strm);

 这样全部编码完成后,关闭MFC和文件。


SsbSipMfcEncClose(hOpen);

fclose(fp_yuv);

fclose(fp_strm);

 至此,编码过程结束了。程序:https://github.com/wuyuans/TQ210/tree/master/MFC,我稍微对API进行了一下包装,写的不太好,见笑了。


关键字:s5pv210  MFC 引用地址:s5pv210中MFC的编码过程

上一篇:S5PV210 时钟体系分析
下一篇:S5PV210刷机时“Uart negotiation Error​​​​​​​​”无法刷机解决办法

推荐阅读最新更新时间:2026-03-22 01:06

s5pv210MFC编码过程
在上一篇《s5pv210中MFC的帧内存格式》中我们知道了MFC编码所需要的格式,现在我们就来看看他的编码过程。首先说一下编码环境,我用的开发板是天嵌的TQ210,运行linux系统,其他开发板差别应该不会很大。 linear mode MFC可以接收两种帧内存格式:linear mode和tile mode,因为tile比较麻烦,我这里就用linear模式来编码。修改MFC_ENC_MAP_FO 在上一篇《s5pv210中MFC的帧内存格式》中我们知道了MFC编码所需要的格式,现在我们就来看看他的编码过程。首先说一下编码环境,我用的开发板是天嵌的TQ210,运行linux系统,其他开发板差别应该不会很大。 linear
[单片机]
S5PV210中的定时器
什么是定时器? 定时器是SoC中常见外设 定时器与计数器。计数器是用来计数的(每隔一个固定时间会计一个数),因为计数器的技术时间周期是固定的,因此到了一定时间,只要用计数值乘以技术的时间周期就能得到一个时间段。这个时间段就是我们定的时间(这就是定时器了)。 定时器/计数器作为SoC的外设,主要用来实现定时执行代码功能,定时器相对于SoC来说,就好像闹钟相对于人来说意义一样 定时器有什么用? 定时器可以让SoC在执行主程序的同时,可以(通过定时器)具有计时功能,到了一定时间(计时结束)后,定时器会产生中断提醒CPU,CPU回去处理中断并执行定时器中断的isr从而去执行预先设定好的事件。 定时器就好像是CPU的秘书一样,这
[单片机]
Linux-3.0.8中基于S5PV210的IRQ模块代码追踪和分析
init/main.c: 1 asmlinkage void start_kernel(void) 2 { 3 ...... 4 early_irq_init(); 5 init_IRQ(); 6 ...... 7 } early_irq_init()函数有两种实现,一种是基于radix tree,一种是定义静态数组,如果要使用radix tree实现的,那么需要打开SPARSE_IRQ配置选项,由于我对数据结构不了解,所以分析以下静态数组实现方式版本的。 /kernel/irq/irqdesc.c 1 struct irq_desc irq_desc __cacheline_aligned_in_
[单片机]
三星s5pv210之芯灵思Sin210与Ti Beaglebone Black之对比
1.外观对比 Ø 芯灵思Sin210 Ø TI Beaglebone Black 2.尺寸对比 Ø 芯灵思Sin210 采用核心板+底板结构,核心板尺寸5CM*6CM;底板尺寸10.6CM*15CM Ø TI Beaglebone Black 8.636cm * 5.334cm 3.配件对比 Ø 芯灵思Sin210 Ø TI Beaglebone Black 只提供一块板子 + miniUSB线 4.液晶LCD对比 Ø 芯灵思Sin210 标配4.3 电阻触摸屏 Ø TI Beaglebone Black 无 5.主打操作系统 Ø 芯灵思Sin210 WinCE Ø TI Beaglebone Bla
[单片机]
三星<font color='red'>s5pv210</font>之芯灵思Sin210与Ti Beaglebone Black之对比
基于s5pv210嵌入式系统busybox文件系统移植
1、下载源码 busybox.net/downloads下载最新版的busybox源码,最新源码为1.21.1 2、解压源码文件 tar xvf busybox-1.21.1.tar.bz2 3、进入busybox cd busybox-1.21.1 4、阅读README文件,查看编译步骤 重点阅读上面一段 5、配置源码 make menuconfig 修改编译工具为交叉编译工具 Busybox Settings --- Build Options--- Cross Compiler prefix为你机器里交叉编译工具链的前缀,我的名字叫arm-none-linux-gnueabi-gcc所以填写arm-none-li
[单片机]
基于<font color='red'>s5pv210</font>嵌入式系统busybox文件系统移植
【ARM裸机s5pv210 】程序烧录
1.SD卡刷uboot   准备工作   (1)securcrt(115200,数据流控制全不选)   (2)usb转串口驱动   (3)破坏iNand中的bootloader已从SD2启动   (4)九鼎x210_fusingtool.exe   (5)准备好的uboot.bin   流程   (1)使用x210_fusingtool将uboot.bin刷入SD卡   (2)板子启动方式选择emmc启动   板子启动流程   开机- 读iNand的uboot失败 - 读SD卡uboot成功 - 运行nandflash中的系统 2.用fastboot刷机   准备工作   (1)OTG数据线,禁用数字签名   (2)fastboo
[单片机]
【ARM裸机s5pv210 】GPIO
GPJ0CON 寄存器共32位,每个引脚用4位控制,16进制的话正好一个数可以控制一个引脚 GPJ0DAT 寄存器共8位,每个引脚用1位控制,16进制的话2个数控制8个引脚 小实验测试: //Makefile文件 led.bin: led.o arm-linux-ld -Ttext 0x0 -o led.elf $^ arm-linux-objcopy -O binary led.elf led.bin %.o : %.S arm-linux-gcc -o $@ $ -c %.o : %.c arm-linux-gcc -o $@ $ -c clean: rm *.o *
[单片机]
【ARM裸机<font color='red'>s5pv210</font> 】GPIO
s5pv210启动debian出错提示bash: cannot set terminal process group (-1): Inappropriate ioctl for device
1.启动参数如下: bootargs=root=/dev/nfs nfsroot=192.168.1.8:/opt/wheezy_fs ip=192.168.1.9:192.168.1.8:192.168.1.1:255.255.255.0::eth0:on init=/bin/bash console=ttySAC0,115200 1.1错误信息如下: bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell 2.修改启动参数: bootargs=root=/dev
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved