1 #define DEBUG_HWACCEL 0
2 #define LOG_TAG "HWACCEL"
3 #include <cutils/log.h>
4 #include <cutils/properties.h>
7 #include "ffmpeg_hwaccel.h"
8 #include "libavutil/hwcontext.h"
9 #include "libavutil/opt.h"
10 #include "libavutil/pixdesc.h"
12 #include "avtools/avconv.h"
17 /* BEGIN: Extracted from ffmpeg_opt.c */
19 const HWAccel hwaccels[] = {
21 { "vdpau", vdpau_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU },
24 { "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA },
27 { "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV },
31 { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI },
33 { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI },
37 { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA },
39 { 0, 0, HWACCEL_NONE, AV_PIX_FMT_NONE },
42 /* END: Extracted from ffmpeg_opt.c */
44 int ffmpeg_hwaccel_get_frame(AVCodecContext *avctx, AVFrame *frame)
47 InputStream *ist = avctx->opaque;
49 if (ist && ist->hwaccel_retrieve_data && frame->format == ist->hwaccel_pix_fmt) {
50 ALOGV_IF(DEBUG_HWACCEL, "ffmpeg_hwaccel_get_frame ctx=%p ist=%p format=%d hwaccel_pix_fmt=%d hwaccel_id=%d",
51 avctx, ist, frame->format, ist->hwaccel_pix_fmt, ist->hwaccel_id);
52 err = ist->hwaccel_retrieve_data(avctx, frame);
54 ist->hwaccel_retrieved_pix_fmt = frame->format;
62 /* BEGIN: Extracted from ffmpeg.c */
64 static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
67 for (i = 0; hwaccels[i].name; i++)
68 if (hwaccels[i].pix_fmt == pix_fmt)
73 static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
75 InputStream *ist = s->opaque;
76 const enum AVPixelFormat *p;
79 for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
80 ALOGD_IF(DEBUG_HWACCEL, "check %td pix_fmts=%d", p - pix_fmts, *p);
81 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
82 const HWAccel *hwaccel;
84 if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
87 hwaccel = get_hwaccel(*p);
89 (ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) ||
90 (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id))
93 ret = hwaccel->init(s);
95 if (ist->hwaccel_id == hwaccel->id) {
96 av_log(NULL, AV_LOG_FATAL,
97 "%s hwaccel requested for input stream #%d, "
98 "but cannot be initialized.\n", hwaccel->name, ist->file_index);
102 if (ist->hw_frames_ctx) {
103 s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx);
104 if (!s->hw_frames_ctx)
105 return AV_PIX_FMT_NONE;
107 ist->active_hwaccel_id = hwaccel->id;
108 ist->hwaccel_pix_fmt = *p;
110 #ifdef LIBAV_CONFIG_H
112 ist->dec_ctx = avcodec_alloc_context3(ist->dec);
113 avcodec_copy_context(ist->dec_ctx, s);
114 ret = hw_device_setup_for_decode(ist);
115 s->hw_device_ctx = ist->dec_ctx->hw_device_ctx;
116 ALOGD_IF(DEBUG_HWACCEL, "hw_device_setup_for_decode: %d ctx=%p hw_device_ctx=%p pix_fmts=%d", ret, s, s->hw_device_ctx, *p);
121 ALOGI("hw codec %s %sabled: s=%p ist=%p pix_fmts=%d", avcodec_get_name(s->codec_id), ret ? "dis" : "en", s, ist, *p);
125 static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
127 InputStream *ist = s->opaque;
128 ALOGV_IF(DEBUG_HWACCEL, "get_buffer: s=%p ist=%p format=%d hwaccel_pix_fmt=%d",
129 s, ist, frame->format, ist->hwaccel_pix_fmt);
131 if (ist->hwaccel_get_buffer && frame->format == ist->hwaccel_pix_fmt)
132 return ist->hwaccel_get_buffer(s, frame, flags);
134 return avcodec_default_get_buffer2(s, frame, flags);
137 /* END: Extracted from ffmpeg.c */
139 int ffmpeg_hwaccel_init(AVCodecContext *avctx)
141 if (!property_get_bool("media.sf.hwaccel", 0))
144 InputStream *ist = av_mallocz(sizeof(*ist));
146 return AVERROR(ENOMEM);
148 ist->hwaccel_id = HWACCEL_AUTO;
149 ist->hwaccel_device = "android";
150 ist->hwaccel_output_format = AV_PIX_FMT_YUV420P;
153 avctx->get_format = get_format;
154 avctx->get_buffer2 = get_buffer;
155 avctx->thread_safe_callbacks = 1;
156 av_opt_set_int(avctx, "refcounted_frames", 1, 0);
158 ALOGD_IF(DEBUG_HWACCEL, "ffmpeg_hwaccel_init ctx=%p ist=%p", avctx, ist);
162 void ffmpeg_hwaccel_deinit(AVCodecContext *avctx)
165 InputStream *ist = avctx->opaque;
166 if (ist->hwaccel_uninit)
167 ist->hwaccel_uninit(avctx);
168 #ifdef LIBAV_CONFIG_H
169 avcodec_free_context(&ist->dec_ctx);
171 av_freep(&avctx->opaque);