分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
=====================================================
FFmpeg的库函数源代码分析文章列表:
【架构图】
【通用】
FFmpeg 源代码简单分析:av_register_all()
FFmpeg 源代码简单分析:avcodec_register_all()
FFmpeg 源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)
FFmpeg 源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)
FFmpeg 源代码简单分析:av_find_decoder()和av_find_encoder()
FFmpeg 源代码简单分析:avcodec_open2()
FFmpeg 源代码简单分析:avcodec_close()
【解码】
图解FFMPEG打开媒体的函数avformat_open_input
FFmpeg 源代码简单分析:avformat_open_input()
FFmpeg 源代码简单分析:avformat_find_stream_info()
FFmpeg 源代码简单分析:av_read_frame()
FFmpeg 源代码简单分析:avcodec_decode_video2()
FFmpeg 源代码简单分析:avformat_close_input()
【编码】
FFmpeg 源代码简单分析:avformat_alloc_output_context2()
FFmpeg 源代码简单分析:avformat_write_header()
FFmpeg 源代码简单分析:avcodec_encode_video()
FFmpeg 源代码简单分析:av_write_frame()
FFmpeg 源代码简单分析:av_write_trailer()
【其它】
FFmpeg源代码简单分析:日志输出系统(av_log()等)
FFmpeg源代码简单分析:结构体成员管理系统-AVClass
FFmpeg源代码简单分析:结构体成员管理系统-AVOption
FFmpeg源代码简单分析:libswscale的sws_getContext()
FFmpeg源代码简单分析:libswscale的sws_scale()
FFmpeg源代码简单分析:libavdevice的avdevice_register_all()
FFmpeg源代码简单分析:libavdevice的gdigrab
【脚本】
【H.264】
=====================================================
打算写两篇文章记录FFmpeg中的图像处理(缩放,YUV/RGB格式转换)类库libswsscale的源代码。libswscale是一个主要用于处理图片像素数据的类库。可以完成图片像素格式的转换,图片的拉伸等工作。有关libswscale的使用可以参考文章:
《最简单的基于FFmpeg的libswscale的示例(YUV转RGB)》
libswscale常用的函数数量很少,一般情况下就3个:
sws_getContext():初始化一个SwsContext。
sws_scale():处理图像数据。
sws_freeContext():释放一个SwsContext。
其中sws_getContext()也可以用sws_getCachedContext()取代。
尽管libswscale从表面上看常用函数的个数不多,它的内部却有一个大大的“世界”。做为一个几乎“万能”的图片像素数据处理类库,它的内部包含了大量的代码。因此计划写两篇文章分析它的源代码。本文首先分析它的初始化函数sws_getContext(),而下一篇文章则分析它的数据处理函数sws_scale()。
函数调用结构图
分析得到的libswscale的函数调用关系如下图所示。
Libswscale处理数据流程
Libswscale处理像素数据的流程可以概括为下图。
从图中可以看出,libswscale处理数据有两条最主要的方式:unscaled和scaled。unscaled用于处理不需要拉伸的像素数据(属于比较特殊的情况),scaled用于处理需要拉伸的像素数据。Unscaled只需要对图像像素格式进行转换;而Scaled则除了对像素格式进行转换之外,还需要对图像进行缩放。Scaled方式可以分成以下几个步骤:
- XXX to YUV Converter:首相将数据像素数据转换为8bitYUV格式;
- Horizontal scaler:水平拉伸图像,并且转换为15bitYUV;
- Vertical scaler:垂直拉伸图像;
- Output converter:转换为输出像素格式。
SwsContext
SwsContext是使用libswscale时候一个贯穿始终的结构体。但是我们在使用FFmpeg的类库进行开发的时候,是无法看到它的内部结构的。在libswscale\swscale.h中只能看到一行定义:struct SwsContext;
一般人看到这个只有一行定义的结构体,会猜测它的内部一定十分简单。但是假使我们看一下FFmpeg的源代码,会发现这个猜测是完全错误的——SwsContext的定义是十分复杂的。它的定义位于libswscale\swscale_internal.h中,如下所示。
/* This struct should be aligned on at least a 32-byte boundary. */typedef struct SwsContext {
/** * info on struct for av_log */ const AVClass *av_class; /** * Note that src, dst, srcStride, dstStride will be copied in the * sws_scale() wrapper so they can be freely modified here. */ SwsFunc swscale; int srcW; ///< Width of source luma/alpha planes. int srcH; ///< Height of source luma/alpha planes. int dstH; ///< Height of destination luma/alpha planes. int chrSrcW; ///< Width of source chroma planes. int chrSrcH; ///< Height of source chroma planes. int chrDstW; ///< Width of destination chroma planes. int chrDstH; ///< Height of destination chroma planes. int lumXInc, chrXInc; int lumYInc, chrYInc; enum AVPixelFormat dstFormat; ///< Destination pixel format. enum AVPixelFormat srcFormat; ///< Source pixel format. int dstFormatBpp; ///< Number of bits per pixel of the destination pixel format. int srcFormatBpp; ///< Number of bits per pixel of the source pixel format. int dstBpc, srcBpc; int chrSrcHSubSample; ///< Binary logarithm of horizontal subsampling factor between luma/alpha and chroma planes in source image. int chrSrcVSubSample; ///< Binary logarithm of vertical subsampling factor between luma/alpha and chroma planes in source image. int chrDstHSubSample; ///< Binary logarithm of horizontal subsampling factor between luma/alpha and chroma planes in destination image. int chrDstVSubSample; ///< Binary logarithm of vertical subsampling factor between luma/alpha and chroma planes in destination image. int vChrDrop; ///< Binary logarithm of extra vertical subsampling factor in source image chroma planes specified by user. int sliceDir; ///< Direction that slices are fed to the scaler (1 = top-to-bottom, -1 = bottom-to-top). double param[2]; ///< Input parameters for scaling algorithms that need them. /* The cascaded_* fields allow spliting a scaler task into multiple * sequential steps, this is for example used to limit the maximum * downscaling factor that needs to be supported in one scaler. */ struct SwsContext *cascaded_context[2]; int cascaded_tmpStride[4]; uint8_t *cascaded_tmp[4]; uint32_t pal_yuv[256]; uint32_t pal_rgb[256]; /** * @name Scaled horizontal lines ring buffer. * The horizontal scaler keeps just enough scaled lines in a ring buffer * so they may be passed to the vertical scaler. The pointers to the * allocated buffers for each line are duplicated in sequence in the ring * buffer to simplify indexing and avoid wrapping around between lines * inside the vertical scaler code. The wrapping is done before the * vertical scaler is called. */ //@{
int16_t **lumPixBuf; ///< Ring buffer for scaled horizontal luma plane lines to be fed to the vertical scaler. int16_t **chrUPixBuf; ///< Ring buffer for scaled horizontal chroma plane lines to be fed to the vertical scaler. int16_t **chrVPixBuf; ///< Ring buffer for scaled horizontal chroma plane lines to be fed to the vertical scaler. int16_t **alpPixBuf; ///< Ring buffer for scaled horizontal alpha plane lines to be fed to the vertical scaler. int vLumBufSize; ///< Number of vertical luma/alpha lines allocated in the ring buffer. int vChrBufSize; ///< Number of vertical chroma lines allocated in the ring buffer. int lastInLumBuf; ///< Last scaled horizontal luma/alpha line from source in the ring buffer. int lastInChrBuf; ///< Last scaled horizontal chroma line from source in the ring buffer. int lumBufIndex; ///< Index in ring buffer of the last scaled horizontal luma/alpha line from source. int chrBufIndex; ///< Index in ring buffer of the last scaled horizontal chroma line from source. //@} uint8_t *formatConvBuffer; /** * @name Horizontal and vertical filters. * To better understand the following fields, here is a pseudo-code of * their usage in filtering a horizontal line: * @code * for (i = 0; i < width; i++) { * dst[i] = 0; * for (j = 0; j < filterSize; j++) * dst[i] += src[ filterPos[i] + j ] * filter[ filterSize * i + j ]; * dst[i] >>= FRAC_BITS; // The actual implementation is fixed-point. * } * @endcode */ //@{
int16_t *hLumFilter; ///< Array of horizontal filter coefficients for luma/alpha planes. int16_t *hChrFilter; ///< Array of horizontal filter coefficients for chroma planes. int16_t *vLumFilter; ///< Array of vertical filter coefficients for luma/alpha planes. int16_t *vChrFilter; ///< Array of vertical filter coefficients for chroma planes. int32_t *hLumFilterPos; ///< Array of horizontal filter starting positions for each dst[i] for luma/alpha planes. int32_t *hChrFilterPos; ///< Array of horizontal filter starting positions for each dst[i] for chroma planes. int32_t *vLumFilterPos; ///< Array of vertical filter starting positions for each dst[i] for luma/alpha planes. int32_t *vChrFilterPos; ///< Array of vertical filter starting positions for each dst[i] for chroma planes. int hLumFilterSize; ///< Horizontal filter size for luma/alpha pixels. int hChrFilterSize; ///< Horizontal filter size for chroma pixels. int vLumFilterSize; ///< Vertical filter size for luma/alpha pixels. int vChrFilterSize; ///< Vertical filter size for chroma pixels. //@} int lumMmxextFilterCodeSize; ///< Runtime-generated MMXEXT horizontal fast bilinear scaler code size for luma/alpha planes. int chrMmxextFilterCodeSize; ///< Runtime-generated MMXEXT horizontal fast bilinear scaler