
s6: 视频研究
文章平均质量分 53
涛歌依旧
毕业后就职于华为和腾讯
展开
-
如何把未压缩的.avi文件批量地转为.yuv文件(yuv420)?
clearclccd('F:\qcifAvi');myFile = dir('*.avi'); % 无损压缩的.avi文件集合for i = 1 : length(myFile) % qcifAvi目录下.avi文件的个数为: length(myFile) name{i} = myFile(i).name(1:length(myFile(i).name)); % .avi文原创 2013-01-06 14:24:55 · 9156 阅读 · 0 评论 -
JM8.6解码端是如何对H.264码流进行读取的?(GetAnnexbNALU 函数)
原始的foreman_part_qcif.yuv文件进行编码后(本人编码的是一帧),生成了test.264文件,现在要用JM8.6解码器对其进行解码,显然,首先要读取码流,然后对码流进行解析. 读二进制的数据,无非就是用到fread, fgetc这样的函数,在代码中简单搜索一下,就很容易定位到我们感兴趣的地方,即:while(!feof(bits) && (Buf[pos++]=fgetc(b原创 2012-11-26 16:12:01 · 10444 阅读 · 0 评论 -
JM8.6解码端是如何从配置文件decoder.cfg获取数据的? (init_conf函数)
在ldecod.c文件的main中调用了init_conf函数,这个函数实际上就实现了程序从配置文件读数据的过程. 之前说过,在JM8.6编码端,Configure函数起着做配置文件encoder_baseline.cfg数据的作用,现在来看看解码端的init_conf函数. main中是这样调用的:init_conf(input, argv[1]); 其中inp原创 2012-11-26 15:42:11 · 9532 阅读 · 3 评论 -
JM8.6中NALU(此处指VCL式的NALU)是如何写进码流的?
在lencod.c的main函数中调用了encode_one_slice函数,在encode_one_slice函数中调用了frame_picture函数,调用了frame_picture函数后(frame_picture还会继续调用其他重要函数) 就实现了对第一帧的编码,这样全局变量frame_pic就发生了变化,得到了它想得到的码流,现在要写码流,怎么写呢? 在encode_on原创 2012-11-25 21:41:03 · 8559 阅读 · 1 评论 -
JM8.6中NALU(此处指非VCL式的NALU,如SPS和PPS)是如何写进码流的?
先看lencod.c中的GenerateParameterSets函数,进入其中:void GenerateParameterSets (){ seq_parameter_set_rbsp_t *sps = NULL; pic_parameter_set_rbsp_t *pps = NULL; sps = AllocSPS(); // 分配堆空间 pps =原创 2012-11-25 16:09:45 · 8566 阅读 · 1 评论 -
JM8.6中的一个重要结构体NALU_t的定义、分配和释放
在JM8.6中,NALU_t是一个非常重要的结构体,回寝室之前,欣赏一下结构体NALU_t的定义:typedef struct { int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested) unsigne原创 2012-11-24 23:34:40 · 8996 阅读 · 0 评论 -
H.264码流分析入门(以第一帧为例)
编码foreman_part_qcif.yuv的第一帧,分析生成的码流,为了便于分析,我们需要打开JM8.6编码器中的trace_enc.txt文件记录功能,怎么开启呢?在JM8.6 encoder的define.h文件中有这样的代码:#if defined _DEBUG#define TRACE 0 //!< 0:Trace off原创 2012-11-24 21:12:02 · 10832 阅读 · 3 评论 -
分析JM8.6中的写码流函数WriteAnnexbNALU
之前已经说过,在JM8.6中写码流函数为WriteAnnexbNALU,如果编码一帧,在WriteAnnexbNALU前打个断点,跟踪代码可以看到该函数被调用了3次,但是奇怪的是,在工程中搜索后,貌似找不到调用WriteAnnexbNALU函数的地方. 在搜索过程中,可以发现这样一个语句:WriteNALU = WriteAnnexbNALU;原来,这里是对函数指针进行了一个赋值原创 2012-11-22 23:08:44 · 8128 阅读 · 1 评论 -
JM8.6代码中究竟是如何把码流写进test.264文件的?
JM8.6编码后,需要将码流写进文件,在默认代码中是写进test.264文件的,写入过程把test.264当成了一个二进制文件,可以用UltraEdit看其中的码流,码流开始部分(本人用的是baseline)一般是:00 00 00 01 67 42...,鉴于test.264是二进制文件,而UltraEdit只相当于一个显示器,让人可以看到其中的比特(并不能复制粘贴其中的比特). 也就原创 2012-11-21 22:20:57 · 14198 阅读 · 15 评论 -
简要分析JM8.6代码中foreman_part_qcif.yuv文件的YUV数据如何悄无声息地进入程序
分析encode_one_frame函数. 先来看下结构体Sourceframe的定义:typedef struct{ // Size info int x_size, y_framesize, y_fieldsize; char *yf, *uf, *vf; //!< frame representatio原创 2012-11-20 20:00:03 · 8748 阅读 · 0 评论 -
用matlab实现一个简单的离群点挖掘(与时序有关)
在视频分析中,需要用到离群点挖掘,下面给出一个简单的离群点挖掘, matlab代码如下:clearclcorgX = [1 1 0 3 4 5 2 70 100 100 100 6 60 3 2 2 1 1 0]k = 3;th = 1;outlier = [];x = newArray(orgX, k)len = length(x);avera原创 2012-11-13 12:08:54 · 11672 阅读 · 1 评论 -
深入剖析H.264的1/2像素(无代码,无真相,彻底弄清分数像素)
H.264的亮度块预测时,支持分数像素,如1/2像素、1/4像素、1/8像素(1/8像素作用不是特别大,现逐渐在取消).开始学习时,对分数像素的理解颇为困难. 其实,分数像素并不是说像素的值是分数形式的,而是说像素的位置是通过插值得来的,认为它的位置在分数位置,体现在运动矢量上就是分数形式的运动矢量. 1/4像素和1/2像素的本质是相同的,为了简便起见,下面仅讨论1/2像素. (视频序列为fore原创 2012-11-12 19:29:54 · 10253 阅读 · 2 评论 -
神奇的Benford law (目前尚未有人能给出Benford law的充分条件和严密的数学证明)
在一数据集中(需要满足一定条件),提取每个数据的首位数字i (i = 1, 2, 3, 4, 5, 6, 7, 8, 9), 发现P(i)并不是1/9, 而是呈现出这样一个规律: P(i) = log10(x + 1) - log10(x). 这就是Benford law, 这也太奇怪了,但很多数据集的确满足或者近似满足Benford law. 下面是matlab计算出的结果: P(i = 1,原创 2012-11-08 20:59:42 · 9007 阅读 · 0 评论 -
用matlab实现一个简单的离群点挖掘(与时序无关)
有时候,在视频特征分析中,要用到离群点挖掘,现给出一个简单的离群点挖掘的例子. 设向量为x = [1 1.1 1.2 1.3 1.4 2 0.2 1.2 1.3 1.4 0.9 1.1 1.2 10]; 那么,如何能挖掘出其中的离群点呢?详见如下matlab代码:clearclck1 = 1;k2 = 1;inlier = [];outli原创 2012-11-08 18:52:20 · 17392 阅读 · 6 评论 -
JM8.6编码器中的Configure函数究竟做了什么?(编程思想:抽象,间接)
从字面意思来看,configure就是配置的意思,顾名思义,Configure函数就是配置函数了。配置函数的作用是给程序配置(设定)一些初始的值,这些值在很大程度上相当于一个开关. 在用别人写的软件的时候,我们经常在软件的界面的某一个对话框里面输入一个参数,然后软件里的程序就会捕捉到这个对话框里面的参数,这样就把用户设定的参数传到了程序里面。细想一下,在JM8.6编码器中就原创 2012-10-30 12:44:33 · 9535 阅读 · 5 评论 -
在JM8.6解码端提取DCT系数和残差并模拟验证itrans函数的功能
如何在JM8.6的解码端提取DCT系数呢?自然而然会想到的问题是:DCT系数从哪里来,要到哪里去,所以,要提取DCT系数,可以看它是哪里产生的,也可以看它要到哪里去,然后在任意一条路上"截击"它,必然能找到DCT系数. 下面找DCT系数的思路是要看DCT系数到哪里去. 很显然,在解码端,DCT系数的下一个动作是进行反DCT变换,所以自然而言找到反DCT变换函数,找了一下,发现itans函数正是反D原创 2012-10-29 17:58:17 · 10471 阅读 · 5 评论 -
JM8.6解码端是如何把像素值写进test_dec.yuv文件的?(write_out_picture函数)
写文件的过程必然涉及到打开文件,所以在代码中找fopen函数,而解码器中的fopen不是很多(如果fopen太多,也可以从fwrite, fputc, putc的角度来找),所以可以很快找到我们感兴趣的代码:if ((p_out=fopen(inp->outfile,"wb"))==0){ snprintf(errortext, ET_SIZE, "Error open file %原创 2012-11-26 21:25:27 · 8389 阅读 · 2 评论 -
如何在VC6.0中成功编译x264?
实在不好意思, 很久不写这个了。原创 2012-12-11 14:42:40 · 7616 阅读 · 3 评论 -
如何把无损压缩的.avi转化成RGB进而转化为YUV420?(cif和qcif都可以)
有一种.avi视频是无损压缩的,实际上是对原始视频的一个封装而已,现把无损压缩的.avi转化成RGB进而转化为YUV. 关于矩阵问题,matlab显然要比C方便太多, 现给出matlab代码:clearclccd('C:\Documents and Settings\Administrator\桌面\matlab');fileName = 'ntia_wfall-qcif_origin原创 2013-01-04 09:57:44 · 10702 阅读 · 0 评论 -
也谈matlab中读取视频的一个重要函数mmreader
在matlab中输入help mmreader来查阅一下该函数,有如下信息:MMREADER Create a multimedia reader object. OBJ = MMREADER(FILENAME) constructs a multimedia reader object, OBJ, that can read in video data from原创 2012-12-31 22:28:23 · 29921 阅读 · 18 评论 -
cif420格式YUV视频的删帧函数
先给出qcif yuv420删帧的matlab代码:% qcif yuv420视频删帧, x是文件名,t1是起始帧,t2是终止帧(删除[t1, t2])% 假定x中的帧数小不超过2400帧function qcif_delete_frames(x, t1, t2)width = 176;height = 144;n = width * height;m = n * 3 /原创 2012-12-31 13:02:53 · 7966 阅读 · 0 评论 -
qcif420格式YUV视频的删帧函数
matlab代码为:% qcif yuv420视频删帧, x是文件名,t1是起始帧,t2是终止帧(删除[t1, t2])% 假定x中的帧数小不超过2400帧function qcif_delete_frames(x, t1, t2)width = 176;height = 144;n = width * height;m = n * 3 / 2; % yuv420fi原创 2012-12-31 13:02:13 · 8237 阅读 · 0 评论 -
如何利用JM8.6解码器提取码流中P帧宏块(所有4*4块)的运动矢量(考虑B帧,设x264编码的12帧为IDR BBPBBPBBPBP)
之前已经讨论过提取P帧各个宏块的第一个4*4块对应的运动矢量,现在考虑提取所有4*4块的运动矢量. 我们知道,在H.264中,宏块是有分块的的,不同情况下分块方式不一样,所以与MPEG2不同,每一个宏块并不只是对应一个运动矢量. 而由于分块的复杂性和多样性,我们可以这样认为:每个4*4块都有一个运动矢量. 比如,对于一个P-skip宏块而言,尽管运动矢量只有一个,但我们认为该宏块的每个4*4块都有原创 2012-12-30 20:19:03 · 11064 阅读 · 10 评论 -
如何利用JM8.6解码器提取码流中P帧宏块(第一个4*4块)的运动矢量(考虑B帧,设x264编码的12帧为IDR BBPBBPBBPBP)
前面已经讨论过,在没有B帧的情况下如何提取P帧的运动矢量,没有考虑B帧. 现在考虑P帧,假设视频有12帧,x264对其进行编码,编码的帧结构为:IDR BBPBBPBBPBP. 故共有4个P帧. (视频格式是qcif格式) 我们知道,在H.264中,P帧中可以有I宏块,本人为了便于数据处理,认为I宏块也有运动矢量,其值为零. 与MPEG2不同的是:在H.264中,一个宏块可原创 2012-12-29 20:49:37 · 10766 阅读 · 1 评论 -
如何利用JM8.6解码器提取码流中P帧宏块的运动矢量(假设编码不用B帧,仅为IDR P P)
在H.264的P帧中,可能有I宏块,skip形式的P宏块和非skip形式的P宏块, I宏块自然不存在运动矢量这一说法. 而skip形式的P宏块和非skip形式的P宏块都是由运动矢量的.(前面已经说过,对于skip形式的宏块而言,像素残差和运动矢量残差都为0) 本人编码3帧,I(IDR) P1 P2. 视频格式是qcif,所以每帧的宏块个数为:99. 用H.264vi原创 2012-12-28 16:42:01 · 9854 阅读 · 13 评论 -
从JM8.6解码器中学习多级指针的应用
在JM8.6中多次出现多级指针,之前的博文已经有介绍多级指针和多级数组的关系. 下面继续来看看多级指针, 以便进一步熟悉.(说明:下面的程序都没有考虑堆内存的释放) 先来简单预热一下:#include typedef unsigned char byte;int main(){ byte a = 0; printf("%d\n", a); b原创 2012-12-27 15:04:15 · 8052 阅读 · 1 评论 -
x264中x264_encoder_open函数欣赏
// 本函数的主要功能是对参数进行修改(赋值/重新赋值) x264_t *x264_encoder_open ( x264_param_t *param ){ x264_t *h = x264_malloc( sizeof( x264_t ) ); int i; // 初始置0 memset( h, 0, sizeof( x264_t ) );原创 2012-12-15 11:36:17 · 11147 阅读 · 0 评论 -
x264中read_frame_yuv函数欣赏
编码300帧的视频,发现read_frame_yuv函数被调用300次. 函数read_frame_yuv的功能是从yuv文件中读取一帧的数据,具体函数定义如下:int read_frame_yuv( x264_picture_t *p_pic, hnd_t handle, int i_frame ){ yuv_input_t *h = handle; if( i_原创 2012-12-15 09:44:13 · 8630 阅读 · 0 评论 -
x264中get_frame_total_yuv函数欣赏(顺便复习和巩固fseek函数和ftell函数的用法)
x264中get_frame_total_yuv函数的作用是计算yuv文件中视频的帧数,定义如下:int get_frame_total_yuv( hnd_t handle ){ yuv_input_t *h = handle; int i_frame_total = 0; if( !fseek( h->fh, 0, SEEK_END ) ) {原创 2012-12-14 22:58:12 · 8208 阅读 · 0 评论 -
x264中x264_cpu_detect函数欣赏
在x264中,x264_cpu_detect函数定义为:uint32_t x264_cpu_detect( void ){ uint32_t cpu = 0; // 定义CPU的型号,初始化为0 uint32_t eax, ebx, ecx, edx; int b_amd; if( !x264_cpu_cpuid_test()原创 2012-12-14 16:23:50 · 9211 阅读 · 1 评论 -
x264中open_file_yuv函数欣赏(顺便谈谈如何利用指针在被调函数中改变主调函数中变量的值)
先来看一个结构体yuv_input_t:typedef struct { FILE *fh; int width, height; int next_frame;} yuv_input_t; yuv_input_t结构体用fh这个文件指针打开原始的yuv文件foreman_qcif.yuv. 但程序中,必须知道yuv文件中视频的尺寸(widt原创 2012-12-13 20:59:55 · 8103 阅读 · 0 评论 -
x264中Parse函数欣赏
我们知道,在x264中,x264_param_default函数对一些参数值进行了设定,现在用户如果需要改变这些默认的参数值,就可以通过命令行配置来修改,具体就是传到argv[i]中去. 下面来看看Parse函数: /* Parse command line */ if( Parse( argc, argv, ¶m, &opt ) < 0 ) re原创 2012-12-12 16:36:04 · 8564 阅读 · 0 评论 -
x264中的 x264_param_default函数欣赏
先看一个简单的程序:#includeusing namespace std;void set(int *p){ *p = 0;}int main(){ int variable; set(&variable); cout << variable << endl; return 0;}下面来看看x264中x26原创 2012-12-12 16:21:22 · 9458 阅读 · 1 评论 -
H.264中整数DCT变换,量化,反量化,反DCT究竟是如何实现的?(无代码,无真相)
H.264中采用的是整数DCT变换,在实现的时候,该变换和量化又杂糅在一起,那么这些错综复杂的关系究竟是怎样纠缠的呢?在参考H.264乐园论坛会员cs1860wd的帖子和H.264 and MPEG-4 VIDEO COMPRESSION(第一版)这本书后,基于帖子和书上的讲解,给出相应的实现代码,并验证代码的正确性. 还是以foreman视频第一帧第一个宏块第一个4*4块原创 2012-10-27 18:12:33 · 21240 阅读 · 17 评论 -
JM8.6中看起来让人不寒而栗的 int ******究竟是怎么回事?
最近又在看H.264的编码器JM8.6, 遇到了很多类似于int ******这样的指针,看起来让人不寒而栗,其实也不过如此,下面用实例来剖析一下:(特此说明一下:为了让程序更简单,下面的程序省略了释放内存的部分)程序1:#includeusing namespace std;int main(){ int a = 0; int b = 1; int原创 2012-10-23 22:05:56 · 8965 阅读 · 5 评论 -
H.264 and MPEG-4 Video Compression Iain E. G. Richardson
书评: 好的教材,当如此也,而不是做成手册。该书是我入门H.264的启蒙书籍,写的非常好,非常清晰,如果你要学习H.264, 该书不可少(请不要看翻译版本,我很不客气地说:翻译的那个版本,很烂),该书已经有了新的版本,我看了一下,新的版本更好,很多例子都更形象,而且新版本中更专注地讲H.264。 虽然以后我不一定做H.264, 但H.264的思想却让我受益匪浅,原创 2013-07-13 21:34:17 · 9803 阅读 · 3 评论 -
JM8.6配置文件中参数的解释
参考JVT-Q042文档,可以学到很多东西. 说明: 不同profile的配置文件中参数一样,只是取值不一样而已,本人认为这样并不好,在baseline的配置文件中带有B帧的信息,非常不好,容易误导人,因为baseline根本就不支持B帧. 下面将对配置文件重要的参数进行解释.########################################################原创 2012-11-22 21:42:55 · 9545 阅读 · 2 评论 -
如何在JM8.6编码端提取QDCT?
毫无疑问,编码端的QDCT和解码端的QDCT完全相同,下面从编码端提取QDCT. 为简便起见,仅提取第一帧第一个宏块第一个4*4块的QDCT.JM8.6编码器最核心的编码函数是encode_one_macroblock,该函数找到了残差并进行了整数DCT变换及量化,然后Zigzag scan和Run-Level编码. 在write_one_macroblock函数中进行了熵编码和写码流, 故在原创 2012-10-27 13:37:37 · 10498 阅读 · 4 评论 -
如何用JM8.6将所有的帧都编码为I帧?
在JM8.6中,如果需要把所有的帧都编码成I帧,只需要将baseline配置文件中的IntraPeriod改为1即可,编码后的结果为:(注意IDR帧是特殊的I帧,后面I帧是普通的I帧,在H.264视频编码中,第一帧必然编码为IDR帧.) 0000(IDR) 21952 0 28 37.376 41.260 42.850 437 0 FRM 99原创 2012-11-17 22:29:50 · 8643 阅读 · 0 评论 -
H.264中的P-Skip宏块和BSkip宏块简介
先说PSkip宏块,再说BSkip宏块. P-Skip宏块是一种特殊的P宏块,在H.264中非常常见,那么P-Skip宏块特殊在什么地方呢?下面会慢慢道来. 对于一般的P宏块而言,像素残差和运动矢量残差都会写入码流,从编码端传到解码端,但是P-Skip宏块的特殊之处就在于,既不传送像素残差,也不传送运动矢量残差(在这种情况下,像素残差和运动矢量残差必定都为零,原创 2012-11-20 11:59:36 · 16723 阅读 · 3 评论