Wednesday, April 29, 2020

Learning ffmpeg

How to install:

https://trac.ffmpeg.org/wiki/CompilationGuide/Centos

 Header

The ffmpeg header files:

extern "C"{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavutil/mem.h"
#include "libavutil/fifo.h"
#include "libswscale/swscale.h"
};

APIs

1. avcodec_init()
/*  Initialize libavcodec.
 *  This function must be called before any other libavcodec functions.
 *  This function is not thread-safe.
 *  # include "libavcodec/avcodec.h"
 *  Implementation: /ffmpeg/libavcodec/utils.c
*/

2. av_register_all()
/**
 * Initialize libavformat and register all the muxers, demuxers, and protocols. If you do not call this function, then you can select exactly which format you want to support.

* av_register_input_format()
* av_register_output_format()
* av_register_protocol()
*
* #include "libavformat/avformat.h"
* Implementation: /ffmpeg/libavformat/allformats.c
*/

3. avformat_alloc_context()
/** Allocate an AVFormatContext
 *  avformat_free_context() can be used to free the context and everything allocated by the framework within it.
*  #include "libavformat/avformat.h"
*  Implementation: /ffmpeg/libavformat/options.c
*/

4. avformat_free_context()
/** Free an AVFormatContext and all its streams.
*    void avformat_free_context(AVFormatContext *s)
*    #include "libavformat/avformat.h"
*    Implementation: /ffmpeg/libavformat/util.c
*
*/

5. avio_alloc_context()

AVIOContext *avio_alloc_context(
unsigned char *buffer,
int buffer_size,
int write_flag,
void *opaque,
int (*read_packet) (void *opaque, uint8_t * buf, int buf_size),
int (*write_packet)(void* opaque, uint8_t * buf, int buf_size),
int64_t(*seek)(void * opaque, int64_t offset, int whence));

6. av_open_input_file()

int av_open_input_file(
AVFormatContext **ic_ptr,
constchar * filename,
AVInputFormat *fmt,
int buf_size,
AVFormatParameters *ap);

7. av_close_input_file()

void av_close_input_file(AVFormatContext *s);

8. av_find_stream_info()

int av_find_stream_info(AVFormatContext* ic)

9. avcodec_find_decoder()
    avcodec_find_decoder_by_name()
    avcodec_find_encoder()
    avcodec_find_encoder_by_name()

10. avcodec_open()
int avcodec_open(AVCodecContext *avctx, AVCodec *codec);

AVOutputFormat *av_guess_format(constchar *short_name,
                                constchar *filename,
                                constchar *mime_type);
// 返回一个已经注册的最合适的输出格式

AVStream *av_new_stream(AVFormatContext *s, int id);
// 为媒体文件添加一个流,一般为作为输出的媒体文件容器添加音视频流

attribute_deprecated void dump_format(AVFormatContext *ic,
                                      int index,
                                      constchar *url,
                                      int is_output);
#endif
// 该函数的作用就是检查下初始化过程中设置的参数是否符合规范
// 有些版本中为 av_dump_format

attribute_deprecated int av_set_parameters(AVFormatContext *s, AVFormatParameters *ap);
// 设置初始化参数
// 不赞成跳过该方法,直接调用 avformat_write_header/av_write_header
attribute_deprecated int av_write_header(AVFormatContext *s);
// 把流头信息写入到媒体文件中
// 返回0成功
1 AVPacket
typedef struct AVPacket {
    /**
     * Presentation timestamp in AVStream->time_base units; the time at which
     * the decompressed packet will be presented to the user.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     * pts MUST be larger or equal to dts as presentation cannot happen before
     * decompression, unless one wants to view hex dumps. Some formats misuse
     * the terms dts and pts/cts to mean something different. Such timestamps
     * must be converted to true pts/dts before they are stored in AVPacket.
     */
    int64_t pts;
    /**
     * Decompression timestamp in AVStream->time_base units; the time at which
     * the packet is decompressed.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     */
    int64_t dts;
    uint8_t *data;
    int   size;
    int   stream_index;
    int   flags;

int   duration;
...
} AVPacket

// AVPacket是个很重要的结构,该结构在读媒体源文件和写输出文件时都需要用到
// int64_t pts; 显示时间戳
// int64_t dts; 解码时间戳
// uint8_t *data; 包数据
// int   size; 包数据长度
// int   stream_index; 包所属流序号
// int   duration; 时长
// 以上信息,如果是在读媒体源文件那么avcodec会初始化,如果是输出文件,用户需要对以上信息赋值
void av_init_packet(AVPacket *pkt);
// 使用默认值初始化AVPacket
// 定义AVPacket对象后,请使用av_init_packet进行初始化
void av_free_packet(AVPacket *pkt);
// 释放AVPacket对象
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
// 从输入源文件容器中读取一个AVPacket数据包
// 该函数读出的包并不每次都是有效的,对于读出的包我们都应该进行相应的解码(视频解码/音频解码),
// 在返回值>=0时,循环调用该函数进行读取,循环调用之前请调用av_free_packet函数清理AVPacket
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,

                         int *got_picture_ptr,

                         AVPacket *avpkt);
// 解码视频流AVPacket
// 使用av_read_frame读取媒体流后需要进行判断,如果为视频流则调用该函数解码
// 返回结果<0时失败,此时程序应该退出检查原因
// 返回>=0时正常,假设 读取包为:AVPacket vPacket 返回值为 int vLen; 每次解码正常时,对vPacket做
// 如下处理:
//   vPacket.size -= vLen;
//   vPacket.data += vLen;
// 如果 vPacket.size==0,则继续读下一流包,否则继续调度该方法进行解码,直到vPacket.size==0
// 返回 got_picture_ptr > 0 时,表示解码到了AVFrame *picture,其后可以对picture进程处理
int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,

                         int *frame_size_ptr,

                         AVPacket *avpkt);

// 解码音频流AVPacket
// 使用av_read_frame读取媒体流后需要进行判断,如果为音频流则调用该函数解码
// 返回结果<0时失败,此时程序应该退出检查原因
// 返回>=0时正常,假设 读取包为:AVPacket vPacket 返回值为 int vLen; 每次解码正常时,对vPacket做
// 如下处理:
//   vPacket.size -= vLen;
//   vPacket.data += vLen;
// 如果 vPacket.size==0,则继续读下一流包,否则继续调度该方法进行解码,直到vPacket.size==0

Data Structures

1. AVFormatContext

typedef struct AVFormatContext{
    struct AVInputFormat        *iformat;
    struct AVOutputFormat     * oformat;
    AVIOContext                      *pb;
    unsigned int                       nb_streams;
    AVStream                          **streams;
    char                                   filename[1024];
    ...
}AVFormatContext;

2. AVIOContext

typedef struct AVIOContext{

}AVIOContext;

3. AVPacket

typedef struct AVPacket {
    /**
     * Presentation timestamp in AVStream->time_base units; the time at which
     * the decompressed packet will be presented to the user.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     * pts MUST be larger or equal to dts as presentation cannot happen before
     * decompression, unless one wants to view hex dumps. Some formats misuse
     * the terms dts and pts/cts to mean something different. Such timestamps
     * must be converted to true pts/dts before they are stored in AVPacket.
     */
    int64_t pts;
    /**
     * Decompression timestamp in AVStream->time_base units; the time at which
     * the packet is decompressed.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     */
    int64_t dts;
    uint8_t *data;
    int   size;
    int   stream_index;
    int   flags;

int   duration;
...
} AVPacket

Reference: 

https://blog.csdn.net/leixiaohua1020/article/details/15811977/