vda: support synchronous decoding.
[ffmpeg.git] / libavcodec / vda_h264.c
1 /*
2  * VDA H264 HW acceleration.
3  *
4  * copyright (c) 2011 Sebastien Zwickert
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "h264.h"
24 #include "vda_internal.h"
25
26 static int start_frame(AVCodecContext *avctx,
27                        av_unused const uint8_t *buffer,
28                        av_unused uint32_t size)
29 {
30     struct vda_context *vda_ctx = avctx->hwaccel_context;
31
32     if (!vda_ctx->decoder)
33         return -1;
34
35     vda_ctx->bitstream_size = 0;
36
37     return 0;
38 }
39
40 static int decode_slice(AVCodecContext *avctx,
41                         const uint8_t *buffer,
42                         uint32_t size)
43 {
44     struct vda_context *vda_ctx = avctx->hwaccel_context;
45     void *tmp;
46
47     if (!vda_ctx->decoder)
48         return -1;
49
50     tmp = av_fast_realloc(vda_ctx->bitstream,
51                           &vda_ctx->ref_size,
52                           vda_ctx->bitstream_size+size+4);
53     if (!tmp)
54         return AVERROR(ENOMEM);
55
56     vda_ctx->bitstream = tmp;
57
58     AV_WB32(vda_ctx->bitstream+vda_ctx->bitstream_size, size);
59     memcpy(vda_ctx->bitstream+vda_ctx->bitstream_size+4, buffer, size);
60
61     vda_ctx->bitstream_size += size + 4;
62
63     return 0;
64 }
65
66 static int end_frame(AVCodecContext *avctx)
67 {
68     H264Context *h = avctx->priv_data;
69     struct vda_context *vda_ctx = avctx->hwaccel_context;
70     AVFrame *frame = &h->s.current_picture_ptr->f;
71     int status;
72
73     if (!vda_ctx->decoder || !vda_ctx->bitstream)
74         return -1;
75
76     if (vda_ctx->use_sync_decoding) {
77         status = ff_vda_sync_decode(vda_ctx);
78         frame->data[3] = (void*)vda_ctx->cv_buffer;
79     } else {
80         status = ff_vda_decoder_decode(vda_ctx, vda_ctx->bitstream,
81                                        vda_ctx->bitstream_size,
82                                        frame->reordered_opaque);
83     }
84
85     if (status)
86         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
87
88     return status;
89 }
90
91 AVHWAccel ff_h264_vda_hwaccel = {
92     .name           = "h264_vda",
93     .type           = AVMEDIA_TYPE_VIDEO,
94     .id             = AV_CODEC_ID_H264,
95     .pix_fmt        = PIX_FMT_VDA_VLD,
96     .start_frame    = start_frame,
97     .decode_slice   = decode_slice,
98     .end_frame      = end_frame,
99 };