1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* @file
* HW-Accelerated decoding example.
*
* @example hw_decode.c
* This example shows how to do HW-accelerated decoding with output
* frames from the HW video surfaces.
*/
av_hwdevice_find_type_by_name();//根据字符串找驱动
/*列举所有驱动字符串
while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
*/
avformat_open_input();//打开封装上下文
avformat_find_stream_info();//查找流信息
av_find_best_stream();//查找匹配的流

for (i = 0;; i++) {
const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i);//根据decoder检索出config
if (!config) {
fprintf(stderr, "Decoder %s does not support device type %s.\n",
decoder->name, av_hwdevice_get_type_name(type));
return -1;
}
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
config->device_type == type) {
hw_pix_fmt = config->pix_fmt;
break;
}
}
avcodec_alloc_context3();//分配并初始化codecCtx
avcodec_parameters_to_context();//根据par填充codecCtx
codecCtx->get_format = get_hw_format;//提供回调

av_hwdevice_ctx_create();//创建驱动上下文
codecCtx->hw_device_ctx = av_buffer_ref(deviceCtx);//创建一个新的引用

avcodec_open2();//根据codec创建codecCtx
while (ret >= 0) {
if ((ret = av_read_frame(input_ctx, &packet)) < 0)//读包
break;
if (video_stream == packet.stream_index)
ret = decode_write(decoder_ctx, &packet);//解
av_packet_unref(&packet);//释放
}
packet.data = NULL;
packet.size = 0;
ret = decode_write(decoder_ctx, &packet);
av_packet_unref(&packet);

avcodec_free_context();
avformat_close_input();
av_buffer_unref();
1
2
3
4
5
6
7
8
9
10
11
12
13
static enum AVPixelFormat get_hw_format(AVCodecContext *ctx,
const enum AVPixelFormat *pix_fmts)
{
const enum AVPixelFormat *p;

for (p = pix_fmts; *p != -1; p++) {
if (*p == hw_pix_fmt)
return *p;
}

fprintf(stderr, "Failed to get HW surface format.\n");
return AV_PIX_FMT_NONE;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static int decode_write(AVCodecContext *avctx, AVPacket *packet)
{
ret = avcodec_send_packet(avctx, packet);//发送到解码器
if (ret < 0) {
return ret;
}
while (1) {
if (!(frame = av_frame_alloc()) || !(sw_frame = av_frame_alloc())) {
ret = AVERROR(ENOMEM);
goto fail;
}
ret = avcodec_receive_frame(avctx, frame);//从解码器中读frame
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_frame_free(&frame);
av_frame_free(&sw_frame);
return 0;
}
else if (ret < 0) {
goto fail;
}
if (frame->format == hw_pix_fmt) {
if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) {//从gpu读到cpu
goto fail;
}
tmp_frame = sw_frame;
}
else
tmp_frame = frame;
size = av_image_get_buffer_size(tmp_frame->format, tmp_frame->width,
tmp_frame->height, 1);//求数据大小
buffer = av_malloc(size);//申请空间
if (!buffer) {
ret = AVERROR(ENOMEM);
goto fail;
}
ret = av_image_copy_to_buffer(buffer, size,
(const uint8_t * const *)tmp_frame->data,
(const int *)tmp_frame->linesize, tmp_frame->format,
tmp_frame->width, tmp_frame->height, 1);//将frame数据复制到buffer
if (ret < 0) {
goto fail;
}
if ((ret = fwrite(buffer, 1, size, output_file)) < 0) {
goto fail;
}
fail:
av_frame_free(&frame);
av_frame_free(&sw_frame);
av_freep(&buffer);
if (ret < 0)
return ret;
}
}