ffmpeg-3-decoder API应用demo

参见代码: test/api/Api-h264-test.c

1. 具体调用过程如下:

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        av_log(NULL, AV_LOG_ERROR, "Incorrect input\n");
        return 1;
    }
    if (video_decode_example(argv[1]) != 0) // 调用decoder
        return 1;
    return 0;
}

static int video_decode_example(const char *input_filename)
{
    // step1: 声明一些参数
    AVCodec *codec = NULL;
    AVCodecContext *ctx= NULL;
    AVCodecParameters *origin_par = NULL;
    AVFrame *fr = NULL;
    uint8_t *byte_buffer = NULL;
    AVPacket pkt;
    AVFormatContext *fmt_ctx = NULL;
    int number_of_written_bytes;
    int video_stream;
    int got_frame = 0;
    int byte_buffer_size;
    int i = 0;
    int result;
    int end_of_stream = 0;

    // step2: 解析头信息
    result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); // //读取文件头部把信息保存到fmt_ctx结构体

    // step3: 给fmt_ctx的stream填充信息
    result = avformat_find_stream_info(fmt_ctx, NULL);
    
    // step4: 找到video stream
    video_stream = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    origin_par = fmt_ctx->streams[video_stream]->codecpar;
 
    // step5: 查找解码器
    codec = avcodec_find_decoder(origin_par->codec_id);
    
    // step6: 创建AVCodecContext结构体。
    ctx = avcodec_alloc_context3(codec);

    // step7: 将音频流信息拷贝到新的AVCodecContext结构体中。
    result = avcodec_parameters_to_context(ctx, origin_par);
   
    // step8: 打开解码器
    result = avcodec_open2(ctx, codec, NULL);

    // step9: 分配空间保存帧数据
    fr = av_frame_alloc();
    
    // step10: 获取buffer size
    byte_buffer_size = av_image_get_buffer_size(ctx->pix_fmt, ctx->width, ctx->height, 16);
   
    // step11: 分配空间
    byte_buffer = av_malloc(byte_buffer_size);
    
    i = 0;
    av_init_packet(&pkt);

    // 循环取出每帧数据进行解码
    do {
        if (!end_of_stream)
            if (av_read_frame(fmt_ctx, &pkt) < 0) // 从流中提取帧数据
                end_of_stream = 1;
        if (end_of_stream) {
            pkt.data = NULL;
            pkt.size = 0;
        }
        if (pkt.stream_index == video_stream || end_of_stream) {
            got_frame = 0;
            if (pkt.pts == AV_NOPTS_VALUE)
                pkt.pts = pkt.dts = i;
            result = avcodec_decode_video2(ctx, fr, &got_frame, &pkt); // 解码视频流
            if (got_frame) {
                number_of_written_bytes = av_image_copy_to_buffer(byte_buffer, byte_buffer_size,
                                        (const uint8_t* const *)fr->data, (const int*) fr->linesize,
                                        ctx->pix_fmt, ctx->width, ctx->height, 1);
                if (number_of_written_bytes < 0) {
                    av_log(NULL, AV_LOG_ERROR, "Can't copy image to buffer\n");
                    return number_of_written_bytes;
                }
            }
            av_packet_unref(&pkt);
            av_init_packet(&pkt);
        }
        i++;
    } while (!end_of_stream || got_frame);

    // 后面做一些列的空间释放,文件关闭等处理
    av_packet_unref(&pkt);
    av_frame_free(&fr);
    avcodec_close(ctx);
    avformat_close_input(&fmt_ctx);
    avcodec_free_context(&ctx);
    av_freep(&byte_buffer);
    return 0;
}

1.2 解码的流程:

ffmpeg-3-decoder API应用demo_第1张图片

 

你可能感兴趣的:(ffmpeg学习)