ffmpeg中关于sws_sacale函数的研究

1.      sws_scale函数进行YUV420转RGB32的时候效率很低,不知是不是ffmpeg程序实

现的问题

2.      进行.mp4文件封装存储的时候,加在视频帧和音频帧后面的时间戳不起作用,

还会导致程序异常,让ffmpeg自己来管理时间戳的话程序就是正常的,但是视频和音频

总是存在不同步的情况

3.      h264转码的效果不好,在windows平台下的vlc播放器(转码也是调用的是

ffmpeg)进行h264的转码,相同的码率,图像分辨率等参数下,windows下转码后的文

件就比linux调用ffmpeg开发出来的软件清晰的多,不知道是不是h264转码设置的参数

有区别。

 

 

 

解答:

1.

我查看了ffmpeg0.5的源代码,看了sws_scale函数,它位于libavcodec/imgresample.c中定义,它的作用主要是进行转码功能,包括分辨率的转换以及颜色空间与格式的转换。

在sws_scale函数中通过调用img_convert函数完成格式的转换。img_convert函数在libavcodec/convert.c中定义,它根据输入文件格式与输出文件格式来决定选取具体的转码函数,比如将YUV420转成RGB32,在img_convert函数中会调用yuv420p_to_rgb32这个函数来转换。

yuv420p_to_rgb32函数在libavcodec/imgconvert_template.c中定义。yuv420p_to_rgb32主要调用了两个宏YUV_TO_RGB1 与YUV_TO_RGB2。这两个宏的定义如下表:

#define YUV_TO_RGB1(cb1, cr1)/

{/

    cb = (cb1) - 128;/

    cr = (cr1) - 128;/

    r_add = FIX(1.40200) * cr + ONE_HALF;/

    g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;/

    b_add = FIX(1.77200) * cb + ONE_HALF;/

}

 

#define YUV_TO_RGB2(r, g, b, y1)/

{/

    y = (y1) << SCALEBITS;/

    r = cm[(y + r_add) >> SCALEBITS];/

    g = cm[(y + g_add) >> SCALEBITS];/

    b = cm[(y + b_add) >> SCALEBITS];/

}

 

这两个宏是颜色空间转换的核心。能够发现从YUV转换成RGB,ffmpeg只是简单地进行了优化:将转换系数通过移位变成整数来避免浮点数的运算; 在将计算出的RGB值限幅到[0,255]时,通过查表来避免分支判断的开销。cm表的初始化通过调用libavcodec/dsputil.c/dsputil_static_init()函数来实现。

由此可见,ffmpeg中将YUV转换成RGB只是进行了很简单的优化,我们在此基础上还可以进一步优化,比如,进一步查表来避免诸如FIX(1.40200) * cr之类的乘法; 另外可以通过使用MMX/SSE指令集来显著加速转换速度。当然,利用具有并行计算能力的GPU架构来并行处理转换过程,则转换速度可以大大提高!

 

2.

         .MP4文件封装中,Movie Header Box中有一个字段time scale来指示文件媒体在1秒时间内的刻度值。封装.mp4时在视频流和音频流中已包含DTS(解码时间戳)和PTS(显示时间戳)。若播放.MP4文件发现音视频不同步,可能是编码时音频流和视频流中的时间戳设置不正确。

 

3.

原因有可能是VLC对FFMPEG中转码中关键算法(如视频重抽样)。H264中重抽样的核心函数是component_resample函数,它位于libavcodec/imgsample.c中。具体的实现我还没有来得及看。


你可能感兴趣的:(windows,优化,linux,算法,header,存储)