先来看一个结构体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文件中视频的尺寸(width, height), 否则,编码器就不知道yuv视频的尺寸,无法编码.
下面来看看open_file_yuv函数:
/* raw 420 yuv file operation */
int open_file_yuv( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
{
// psz_filename 指向了 "foreman_qcif.yuv"这个串
yuv_input_t *h = malloc(sizeof(yuv_input_t));
h->width = p_param->i_width; // 帧宽:如176
h->height = p_param->i_height; // 帧高:如144
h->next_frame = 0;
if( !strcmp(psz_filename, "-") )
h->fh = stdin;
else
h->fh = fopen(psz_filename, "rb"); // 打开foreman_qcif.yuv文件
if( h->fh == NULL )
return -1;
*p_handle = (hnd_t)h; // p_handle实际上是指向指针的指针
return 0;
}
open_file_yuv函数在哪里被调用呢?看x264文件中的Parse函数中的语句:
p_open_infile = open_file_yuv; // 函数指针赋值
继续看:
if( p_open_infile( psz_filename, &opt->hin, param ) ) // opt->hin是指针变量,&opt->hin是指针变量的地址
{
fprintf( stderr, "x264 [error]: could not open input file '%s'\n", psz_filename );
return -1;
}
实际上,在此处调用到了open_file_yuv函数. 通过调用open_file_yuv函数后,opt->hin实际上就相当于保住了open_file_yuv函数中的局部指针变量h. 也的确需要保住这个h, 因为h指向了申请的堆,open_file_yuv函数调用后,h自动没有了,你不保住h, 怎么行呢?怎能访问和操作申请的对空间呢?调用完后,opt->hin这个指针变量就指向了堆内存. 看看open_file_yuv函数中的yuv_input_t *h = malloc(sizeof(yuv_input_t));就明白了.
那为什么要用到函数指针呢?很明显,是为了抽象,越抽象,越通用. 抽象是一种非常重要的编程思想,要掌握啊.
最后看两个简单的例子,补一补C语言知识: (被调函数如何改变主调函数中变量的值?你被掉函数要改变主函数中变量的值,你倒是搞个指针变量指向主调函数中的变量啊!)
#include <stdio.h>
void myFun(int *p)
{
*p = 0;
}
int main()
{
int a = 100;
myFun(&a);
printf("%d\n", a);
return 0;
}
#include <stdio.h>
#include <malloc.h>
void myAlloc(int **q)
{
*q = (int *)malloc(sizeof(int));
**q = 0;
}
int main()
{
int *p;
myAlloc(&p);
printf("%d\n", *p);
free(p);
return 0;
}