Unified · Split
| @@ -15,6 +15,8 @@ API changes, most recent first: · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | 2016-xx-xx - lavu 55.6.0 | 16 | 2016-xx-xx - lavu 55.6.0 |
| 17 | xxxxxxx buffer.h - Add av_buffer_pool_init2(). | 17 | xxxxxxx buffer.h - Add av_buffer_pool_init2(). |
| 18 | xxxxxxx hwcontext.h - Add a new installed header hwcontext.h with a new API | ||
| 19 | for handling hwaccel frames. | ||
| 18 | 20 | ||
| 19 | 2016-xx-xx - xxxxxxx - lavf 57.3.0 - avformat.h | 21 | 2016-xx-xx - xxxxxxx - lavf 57.3.0 - avformat.h |
| 20 | Add AVFormatContext.opaque, io_open and io_close, allowing custom IO | 22 | Add AVFormatContext.opaque, io_open and io_close, allowing custom IO |
| @@ -23,6 +23,7 @@ HEADERS = adler32.h \ · 22 unmodified lines | |||
| 23 | file.h \ | 23 | file.h \ |
| 24 | frame.h \ | 24 | frame.h \ |
| 25 | hmac.h \ | 25 | hmac.h \ |
| 26 | hwcontext.h \ | ||
| 26 | imgutils.h \ | 27 | imgutils.h \ |
| 27 | intfloat.h \ | 28 | intfloat.h \ |
| 28 | intreadwrite.h \ | 29 | intreadwrite.h \ |
| @@ -78,6 +79,7 @@ OBJS = adler32.o \ · 49 unmodified lines | |||
| 78 | float_dsp.o \ | 79 | float_dsp.o \ |
| 79 | frame.o \ | 80 | frame.o \ |
| 80 | hmac.o \ | 81 | hmac.o \ |
| 82 | hwcontext.o \ | ||
| 81 | imgutils.o \ | 83 | imgutils.o \ |
| 82 | intmath.o \ | 84 | intmath.o \ |
| 83 | lfg.o \ | 85 | lfg.o \ |
| @@ -251,6 +251,14 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) · 250 unmodified lines | |||
| 251 | } | 251 | } |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | if (src->hw_frames_ctx) { | ||
| 255 | dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx); | ||
| 256 | if (!dst->hw_frames_ctx) { | ||
| 257 | ret = AVERROR(ENOMEM); | ||
| 258 | goto fail; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 254 | /* duplicate extended data */ | 262 | /* duplicate extended data */ |
| 255 | if (src->extended_data != src->data) { | 263 | if (src->extended_data != src->data) { |
| 256 | int ch = av_get_channel_layout_nb_channels(src->channel_layout); | 264 | int ch = av_get_channel_layout_nb_channels(src->channel_layout); |
| @@ -303,6 +311,9 @@ void av_frame_unref(AVFrame *frame) · 46 unmodified lines | |||
| 303 | for (i = 0; i < frame->nb_extended_buf; i++) | 311 | for (i = 0; i < frame->nb_extended_buf; i++) |
| 304 | av_buffer_unref(&frame->extended_buf[i]); | 312 | av_buffer_unref(&frame->extended_buf[i]); |
| 305 | av_freep(&frame->extended_buf); | 313 | av_freep(&frame->extended_buf); |
| 314 | |||
| 315 | av_buffer_unref(&frame->hw_frames_ctx); | ||
| 316 | |||
| 306 | get_frame_defaults(frame); | 317 | get_frame_defaults(frame); |
| 307 | } | 318 | } |
| 308 | 319 | ||
| @@ -354,6 +354,12 @@ typedef struct AVFrame { · 353 unmodified lines | |||
| 354 | enum AVColorSpace colorspace; | 354 | enum AVColorSpace colorspace; |
| 355 | 355 | ||
| 356 | enum AVChromaLocation chroma_location; | 356 | enum AVChromaLocation chroma_location; |
| 357 | |||
| 358 | /** | ||
| 359 | * For hwaccel-format frames, this should be a reference to the | ||
| 360 | * AVHWFramesContext describing the frame. | ||
| 361 | */ | ||
| 362 | AVBufferRef *hw_frames_ctx; | ||
| 357 | } AVFrame; | 363 | } AVFrame; |
| 358 | 364 | ||
| 359 | /** | 365 | /** |
| @@ -0,0 +1,396 @@ | |||
| 1 | /* | ||
| 2 | * This file is part of Libav. | ||
| 3 | * | ||
| 4 | * Libav is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2.1 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Libav is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Lesser General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||
| 15 | * License along with Libav; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include "config.h" | ||
| 20 | |||
| 21 | #include "buffer.h" | ||
| 22 | #include "common.h" | ||
| 23 | #include "hwcontext.h" | ||
| 24 | #include "hwcontext_internal.h" | ||
| 25 | #include "imgutils.h" | ||
| 26 | #include "log.h" | ||
| 27 | #include "mem.h" | ||
| 28 | #include "pixdesc.h" | ||
| 29 | #include "pixfmt.h" | ||
| 30 | |||
| 31 | static const HWContextType *hw_table[] = { | ||
| 32 | NULL, | ||
| 33 | }; | ||
| 34 | |||
| 35 | static const AVClass hwdevice_ctx_class = { | ||
| 36 | .class_name = "AVHWDeviceContext", | ||
| 37 | .item_name = av_default_item_name, | ||
| 38 | .version = LIBAVUTIL_VERSION_INT, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static void hwdevice_ctx_free(void *opaque, uint8_t *data) | ||
| 42 | { | ||
| 43 | AVHWDeviceContext *ctx = (AVHWDeviceContext*)data; | ||
| 44 | |||
| 45 | /* uninit might still want access the hw context and the user | ||
| 46 | * free() callback might destroy it, so uninit has to be called first */ | ||
| 47 | if (ctx->internal->hw_type->device_uninit) | ||
| 48 | ctx->internal->hw_type->device_uninit(ctx); | ||
| 49 | |||
| 50 | if (ctx->free) | ||
| 51 | ctx->free(ctx); | ||
| 52 | |||
| 53 | av_freep(&ctx->hwctx); | ||
| 54 | av_freep(&ctx->internal->priv); | ||
| 55 | av_freep(&ctx->internal); | ||
| 56 | av_freep(&ctx); | ||
| 57 | } | ||
| 58 | |||
| 59 | AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type) | ||
| 60 | { | ||
| 61 | AVHWDeviceContext *ctx; | ||
| 62 | AVBufferRef *buf; | ||
| 63 | const HWContextType *hw_type = NULL; | ||
| 64 | int i; | ||
| 65 | |||
| 66 | for (i = 0; hw_table[i]; i++) { | ||
| 67 | if (hw_table[i]->type == type) { | ||
| 68 | hw_type = hw_table[i]; | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | if (!hw_type) | ||
| 73 | return NULL; | ||
| 74 | |||
| 75 | ctx = av_mallocz(sizeof(*ctx)); | ||
| 76 | if (!ctx) | ||
| 77 | return NULL; | ||
| 78 | |||
| 79 | ctx->internal = av_mallocz(sizeof(*ctx->internal)); | ||
| 80 | if (!ctx->internal) | ||
| 81 | goto fail; | ||
| 82 | |||
| 83 | if (hw_type->device_priv_size) { | ||
| 84 | ctx->internal->priv = av_mallocz(hw_type->device_priv_size); | ||
| 85 | if (!ctx->internal->priv) | ||
| 86 | goto fail; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (hw_type->device_hwctx_size) { | ||
| 90 | ctx->hwctx = av_mallocz(hw_type->device_hwctx_size); | ||
| 91 | if (!ctx->hwctx) | ||
| 92 | goto fail; | ||
| 93 | } | ||
| 94 | |||
| 95 | buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), | ||
| 96 | hwdevice_ctx_free, NULL, | ||
| 97 | AV_BUFFER_FLAG_READONLY); | ||
| 98 | if (!buf) | ||
| 99 | goto fail; | ||
| 100 | |||
| 101 | ctx->type = type; | ||
| 102 | ctx->av_class = &hwdevice_ctx_class; | ||
| 103 | |||
| 104 | ctx->internal->hw_type = hw_type; | ||
| 105 | |||
| 106 | return buf; | ||
| 107 | |||
| 108 | fail: | ||
| 109 | if (ctx->internal) | ||
| 110 | av_freep(&ctx->internal->priv); | ||
| 111 | av_freep(&ctx->internal); | ||
| 112 | av_freep(&ctx->hwctx); | ||
| 113 | av_freep(&ctx); | ||
| 114 | return NULL; | ||
| 115 | } | ||
| 116 | |||
| 117 | int av_hwdevice_ctx_init(AVBufferRef *ref) | ||
| 118 | { | ||
| 119 | AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data; | ||
| 120 | int ret; | ||
| 121 | |||
| 122 | if (ctx->internal->hw_type->device_init) { | ||
| 123 | ret = ctx->internal->hw_type->device_init(ctx); | ||
| 124 | if (ret < 0) | ||
| 125 | goto fail; | ||
| 126 | } | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | fail: | ||
| 130 | if (ctx->internal->hw_type->device_uninit) | ||
| 131 | ctx->internal->hw_type->device_uninit(ctx); | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | |||
| 135 | static const AVClass hwframe_ctx_class = { | ||
| 136 | .class_name = "AVHWFramesContext", | ||
| 137 | .item_name = av_default_item_name, | ||
| 138 | .version = LIBAVUTIL_VERSION_INT, | ||
| 139 | }; | ||
| 140 | |||
| 141 | static void hwframe_ctx_free(void *opaque, uint8_t *data) | ||
| 142 | { | ||
| 143 | AVHWFramesContext *ctx = (AVHWFramesContext*)data; | ||
| 144 | |||
| 145 | if (ctx->internal->pool_internal) | ||
| 146 | av_buffer_pool_uninit(&ctx->internal->pool_internal); | ||
| 147 | |||
| 148 | if (ctx->internal->hw_type->frames_uninit) | ||
| 149 | ctx->internal->hw_type->frames_uninit(ctx); | ||
| 150 | |||
| 151 | if (ctx->free) | ||
| 152 | ctx->free(ctx); | ||
| 153 | |||
| 154 | av_buffer_unref(&ctx->device_ref); | ||
| 155 | |||
| 156 | av_freep(&ctx->hwctx); | ||
| 157 | av_freep(&ctx->internal->priv); | ||
| 158 | av_freep(&ctx->internal); | ||
| 159 | av_freep(&ctx); | ||
| 160 | } | ||
| 161 | |||
| 162 | AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in) | ||
| 163 | { | ||
| 164 | AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data; | ||
| 165 | const HWContextType *hw_type = device_ctx->internal->hw_type; | ||
| 166 | AVHWFramesContext *ctx; | ||
| 167 | AVBufferRef *buf, *device_ref = NULL;; | ||
| 168 | |||
| 169 | ctx = av_mallocz(sizeof(*ctx)); | ||
| 170 | if (!ctx) | ||
| 171 | return NULL; | ||
| 172 | |||
| 173 | ctx->internal = av_mallocz(sizeof(*ctx->internal)); | ||
| 174 | if (!ctx->internal) | ||
| 175 | goto fail; | ||
| 176 | |||
| 177 | if (hw_type->frames_priv_size) { | ||
| 178 | ctx->internal->priv = av_mallocz(hw_type->frames_priv_size); | ||
| 179 | if (!ctx->internal->priv) | ||
| 180 | goto fail; | ||
| 181 | } | ||
| 182 | |||
| 183 | if (hw_type->frames_hwctx_size) { | ||
| 184 | ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size); | ||
| 185 | if (!ctx->hwctx) | ||
| 186 | goto fail; | ||
| 187 | } | ||
| 188 | |||
| 189 | device_ref = av_buffer_ref(device_ref_in); | ||
| 190 | if (!device_ref) | ||
| 191 | goto fail; | ||
| 192 | |||
| 193 | buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx), | ||
| 194 | hwframe_ctx_free, NULL, | ||
| 195 | AV_BUFFER_FLAG_READONLY); | ||
| 196 | if (!buf) | ||
| 197 | goto fail; | ||
| 198 | |||
| 199 | ctx->av_class = &hwframe_ctx_class; | ||
| 200 | ctx->device_ref = device_ref; | ||
| 201 | ctx->device_ctx = device_ctx; | ||
| 202 | ctx->format = AV_PIX_FMT_NONE; | ||
| 203 | |||
| 204 | ctx->internal->hw_type = hw_type; | ||
| 205 | |||
| 206 | return buf; | ||
| 207 | |||
| 208 | fail: | ||
| 209 | if (device_ref) | ||
| 210 | av_buffer_unref(&device_ref); | ||
| 211 | if (ctx->internal) | ||
| 212 | av_freep(&ctx->internal->priv); | ||
| 213 | av_freep(&ctx->internal); | ||
| 214 | av_freep(&ctx->hwctx); | ||
| 215 | av_freep(&ctx); | ||
| 216 | return NULL; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int hwframe_pool_prealloc(AVBufferRef *ref) | ||
| 220 | { | ||
| 221 | AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data; | ||
| 222 | AVFrame **frames; | ||
| 223 | int i, ret = 0; | ||
| 224 | |||
| 225 | frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames)); | ||
| 226 | if (!frames) | ||
| 227 | return AVERROR(ENOMEM); | ||
| 228 | |||
| 229 | for (i = 0; i < ctx->initial_pool_size; i++) { | ||
| 230 | frames[i] = av_frame_alloc(); | ||
| 231 | if (!frames[i]) | ||
| 232 | goto fail; | ||
| 233 | |||
| 234 | ret = av_hwframe_get_buffer(ref, frames[i], 0); | ||
| 235 | if (ret < 0) | ||
| 236 | goto fail; | ||
| 237 | } | ||
| 238 | |||
| 239 | fail: | ||
| 240 | for (i = 0; i < ctx->initial_pool_size; i++) | ||
| 241 | av_frame_free(&frames[i]); | ||
| 242 | av_freep(&frames); | ||
| 243 | |||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | |||
| 247 | int av_hwframe_ctx_init(AVBufferRef *ref) | ||
| 248 | { | ||
| 249 | AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data; | ||
| 250 | const enum AVPixelFormat *pix_fmt; | ||
| 251 | int ret; | ||
| 252 | |||
| 253 | /* validate the pixel format */ | ||
| 254 | for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) { | ||
| 255 | if (*pix_fmt == ctx->format) | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | if (*pix_fmt == AV_PIX_FMT_NONE) { | ||
| 259 | av_log(ctx, AV_LOG_ERROR, | ||
| 260 | "The hardware pixel format '%s' is not supported by the device type '%s'\n", | ||
| 261 | av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name); | ||
| 262 | return AVERROR(ENOSYS); | ||
| 263 | } | ||
| 264 | |||
| 265 | /* validate the dimensions */ | ||
| 266 | ret = av_image_check_size(ctx->width, ctx->height, 0, ctx); | ||
| 267 | if (ret < 0) | ||
| 268 | return ret; | ||
| 269 | |||
| 270 | /* format-specific init */ | ||
| 271 | if (ctx->internal->hw_type->frames_init) { | ||
| 272 | ret = ctx->internal->hw_type->frames_init(ctx); | ||
| 273 | if (ret < 0) | ||
| 274 | goto fail; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (ctx->internal->pool_internal && !ctx->pool) | ||
| 278 | ctx->pool = ctx->internal->pool_internal; | ||
| 279 | |||
| 280 | /* preallocate the frames in the pool, if requested */ | ||
| 281 | if (ctx->initial_pool_size > 0) { | ||
| 282 | ret = hwframe_pool_prealloc(ref); | ||
| 283 | if (ret < 0) | ||
| 284 | goto fail; | ||
| 285 | } | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | fail: | ||
| 289 | if (ctx->internal->hw_type->frames_uninit) | ||
| 290 | ctx->internal->hw_type->frames_uninit(ctx); | ||
| 291 | return ret; | ||
| 292 | } | ||
| 293 | |||
| 294 | int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, | ||
| 295 | enum AVHWFrameTransferDirection dir, | ||
| 296 | enum AVPixelFormat **formats, int flags) | ||
| 297 | { | ||
| 298 | AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; | ||
| 299 | |||
| 300 | if (!ctx->internal->hw_type->transfer_get_formats) | ||
| 301 | return AVERROR(ENOSYS); | ||
| 302 | |||
| 303 | return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats); | ||
| 304 | } | ||
| 305 | |||
| 306 | static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags) | ||
| 307 | { | ||
| 308 | AVFrame *frame_tmp; | ||
| 309 | int ret = 0; | ||
| 310 | |||
| 311 | frame_tmp = av_frame_alloc(); | ||
| 312 | if (!frame_tmp) | ||
| 313 | return AVERROR(ENOMEM); | ||
| 314 | |||
| 315 | /* if the format is set, use that | ||
| 316 | * otherwise pick the first supported one */ | ||
| 317 | if (dst->format >= 0) { | ||
| 318 | frame_tmp->format = dst->format; | ||
| 319 | } else { | ||
| 320 | enum AVPixelFormat *formats; | ||
| 321 | |||
| 322 | ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx, | ||
| 323 | AV_HWFRAME_TRANSFER_DIRECTION_FROM, | ||
| 324 | &formats, 0); | ||
| 325 | if (ret < 0) | ||
| 326 | goto fail; | ||
| 327 | frame_tmp->format = formats[0]; | ||
| 328 | av_freep(&formats); | ||
| 329 | } | ||
| 330 | frame_tmp->width = src->width; | ||
| 331 | frame_tmp->height = src->height; | ||
| 332 | |||
| 333 | ret = av_frame_get_buffer(frame_tmp, 32); | ||
| 334 | if (ret < 0) | ||
| 335 | goto fail; | ||
| 336 | |||
| 337 | ret = av_hwframe_transfer_data(frame_tmp, src, flags); | ||
| 338 | if (ret < 0) | ||
| 339 | goto fail; | ||
| 340 | |||
| 341 | av_frame_move_ref(dst, frame_tmp); | ||
| 342 | |||
| 343 | fail: | ||
| 344 | av_frame_free(&frame_tmp); | ||
| 345 | return ret; | ||
| 346 | } | ||
| 347 | |||
| 348 | int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags) | ||
| 349 | { | ||
| 350 | AVHWFramesContext *ctx; | ||
| 351 | int ret; | ||
| 352 | |||
| 353 | if (!dst->buf[0]) | ||
| 354 | return transfer_data_alloc(dst, src, flags); | ||
| 355 | |||
| 356 | if (src->hw_frames_ctx) { | ||
| 357 | ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; | ||
| 358 | |||
| 359 | ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src); | ||
| 360 | if (ret < 0) | ||
| 361 | return ret; | ||
| 362 | } else if (dst->hw_frames_ctx) { | ||
| 363 | ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data; | ||
| 364 | |||
| 365 | ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src); | ||
| 366 | if (ret < 0) | ||
| 367 | return ret; | ||
| 368 | } else | ||
| 369 | return AVERROR(ENOSYS); | ||
| 370 | |||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags) | ||
| 375 | { | ||
| 376 | AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data; | ||
| 377 | int ret; | ||
| 378 | |||
| 379 | if (!ctx->internal->hw_type->frames_get_buffer) | ||
| 380 | return AVERROR(ENOSYS); | ||
| 381 | |||
| 382 | if (!ctx->pool) | ||
| 383 | return AVERROR(EINVAL); | ||
| 384 | |||
| 385 | frame->hw_frames_ctx = av_buffer_ref(hwframe_ref); | ||
| 386 | if (!frame->hw_frames_ctx) | ||
| 387 | return AVERROR(ENOMEM); | ||
| 388 | |||
| 389 | ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame); | ||
| 390 | if (ret < 0) { | ||
| 391 | av_buffer_unref(&frame->hw_frames_ctx); | ||
| 392 | return ret; | ||
| 393 | } | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | } | ||
| @@ -0,0 +1,328 @@ | |||
| 1 | /* | ||
| 2 | * This file is part of Libav. | ||
| 3 | * | ||
| 4 | * Libav is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2.1 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Libav is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Lesser General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||
| 15 | * License along with Libav; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef AVUTIL_HWCONTEXT_H | ||
| 20 | #define AVUTIL_HWCONTEXT_H | ||
| 21 | |||
| 22 | #include "buffer.h" | ||
| 23 | #include "frame.h" | ||
| 24 | #include "log.h" | ||
| 25 | #include "pixfmt.h" | ||
| 26 | |||
| 27 | enum AVHWDeviceType { | ||
| 28 | AV_HWDEVICE_TYPE_VDPAU, | ||
| 29 | }; | ||
| 30 | |||
| 31 | typedef struct AVHWDeviceInternal AVHWDeviceInternal; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * This struct aggregates all the (hardware/vendor-specific) "high-level" state, | ||
| 35 | * i.e. state that is not tied to a concrete processing configuration. | ||
| 36 | * E.g., in an API that supports hardware-accelerated encoding and decoding, | ||
| 37 | * this struct will (if possible) wrap the state that is common to both encoding | ||
| 38 | * and decoding and from which specific instances of encoders or decoders can be | ||
| 39 | * derived. | ||
| 40 | * | ||
| 41 | * This struct is reference-counted with the AVBuffer mechanism. The | ||
| 42 | * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field | ||
| 43 | * points to the actual AVHWDeviceContext. Further objects derived from | ||
| 44 | * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with | ||
| 45 | * specific properties) will hold an internal reference to it. After all the | ||
| 46 | * references are released, the AVHWDeviceContext itself will be freed, | ||
| 47 | * optionally invoking a user-specified callback for uninitializing the hardware | ||
| 48 | * state. | ||
| 49 | */ | ||
| 50 | typedef struct AVHWDeviceContext { | ||
| 51 | /** | ||
| 52 | * A class for logging. Set by av_hwdevice_ctx_alloc(). | ||
| 53 | */ | ||
| 54 | const AVClass *av_class; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Private data used internally by libavutil. Must not be accessed in any | ||
| 58 | * way by the caller. | ||
| 59 | */ | ||
| 60 | AVHWDeviceInternal *internal; | ||
| 61 | |||
| 62 | /** | ||
| 63 | * This field identifies the underlying API used for hardware access. | ||
| 64 | * | ||
| 65 | * This field is set when this struct is allocated and never changed | ||
| 66 | * afterwards. | ||
| 67 | */ | ||
| 68 | enum AVHWDeviceType type; | ||
| 69 | |||
| 70 | /** | ||
| 71 | * The format-specific data, allocated and freed by libavutil along with | ||
| 72 | * this context. | ||
| 73 | * | ||
| 74 | * Should be cast by the user to the format-specific context defined in the | ||
| 75 | * corresponding header (hwcontext_*.h) and filled as described in the | ||
| 76 | * documentation before calling av_hwdevice_ctx_init(). | ||
| 77 | * | ||
| 78 | * After calling av_hwdevice_ctx_init() this struct should not be modified | ||
| 79 | * by the caller. | ||
| 80 | */ | ||
| 81 | void *hwctx; | ||
| 82 | |||
| 83 | /** | ||
| 84 | * This field may be set by the caller before calling av_hwdevice_ctx_init(). | ||
| 85 | * | ||
| 86 | * If non-NULL, this callback will be called when the last reference to | ||
| 87 | * this context is unreferenced, immediately before it is freed. | ||
| 88 | * | ||
| 89 | * @note when other objects (e.g an AVHWFramesContext) are derived from this | ||
| 90 | * struct, this callback will be invoked after all such child objects | ||
| 91 | * are fully uninitialized and their respective destructors invoked. | ||
| 92 | */ | ||
| 93 | void (*free)(struct AVHWDeviceContext *ctx); | ||
| 94 | |||
| 95 | /** | ||
| 96 | * Arbitrary user data, to be used e.g. by the free() callback. | ||
| 97 | */ | ||
| 98 | void *user_opaque; | ||
| 99 | } AVHWDeviceContext; | ||
| 100 | |||
| 101 | typedef struct AVHWFramesInternal AVHWFramesInternal; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * This struct describes a set or pool of "hardware" frames (i.e. those with | ||
| 105 | * data not located in normal system memory). All the frames in the pool are | ||
| 106 | * assumed to be allocated in the same way and interchangeable. | ||
| 107 | * | ||
| 108 | * This struct is reference-counted with the AVBuffer mechanism and tied to a | ||
| 109 | * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor | ||
| 110 | * yields a reference, whose data field points to the actual AVHWFramesContext | ||
| 111 | * struct. | ||
| 112 | */ | ||
| 113 | typedef struct AVHWFramesContext { | ||
| 114 | /** | ||
| 115 | * A class for logging. | ||
| 116 | */ | ||
| 117 | const AVClass *av_class; | ||
| 118 | |||
| 119 | /** | ||
| 120 | * Private data used internally by libavutil. Must not be accessed in any | ||
| 121 | * way by the caller. | ||
| 122 | */ | ||
| 123 | AVHWFramesInternal *internal; | ||
| 124 | |||
| 125 | /** | ||
| 126 | * A reference to the parent AVHWDeviceContext. This reference is owned and | ||
| 127 | * managed by the enclosing AVHWFramesContext, but the caller may derive | ||
| 128 | * additional references from it. | ||
| 129 | */ | ||
| 130 | AVBufferRef *device_ref; | ||
| 131 | |||
| 132 | /** | ||
| 133 | * The parent AVHWDeviceContext. This is simply a pointer to | ||
| 134 | * device_ref->data provided for convenience. | ||
| 135 | * | ||
| 136 | * Set by libavutil in av_hwframe_ctx_init(). | ||
| 137 | */ | ||
| 138 | AVHWDeviceContext *device_ctx; | ||
| 139 | |||
| 140 | /** | ||
| 141 | * The format-specific data, allocated and freed automatically along with | ||
| 142 | * this context. | ||
| 143 | * | ||
| 144 | * Should be cast by the user to the format-specific context defined in the | ||
| 145 | * corresponding header (hwframe_*.h) and filled as described in the | ||
| 146 | * documentation before calling av_hwframe_ctx_init(). | ||
| 147 | * | ||
| 148 | * After any frames using this context are created, the contents of this | ||
| 149 | * struct should not be modified by the caller. | ||
| 150 | */ | ||
| 151 | void *hwctx; | ||
| 152 | |||
| 153 | /** | ||
| 154 | * This field may be set by the caller before calling av_hwframe_ctx_init(). | ||
| 155 | * | ||
| 156 | * If non-NULL, this callback will be called when the last reference to | ||
| 157 | * this context is unreferenced, immediately before it is freed. | ||
| 158 | */ | ||
| 159 | void (*free)(struct AVHWFramesContext *ctx); | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Arbitrary user data, to be used e.g. by the free() callback. | ||
| 163 | */ | ||
| 164 | void *user_opaque; | ||
| 165 | |||
| 166 | /** | ||
| 167 | * A pool from which the frames are allocated by av_hwframe_get_buffer(). | ||
| 168 | * This field may be set by the caller before calling av_hwframe_ctx_init(). | ||
| 169 | * The buffers returned by calling av_buffer_pool_get() on this pool must | ||
| 170 | * have the properties described in the documentation in the correponding hw | ||
| 171 | * type's header (hwcontext_*.h). The pool will be freed strictly before | ||
| 172 | * this struct's free() callback is invoked. | ||
| 173 | * | ||
| 174 | * This field may be NULL, then libavutil will attempt to allocate a pool | ||
| 175 | * internally. Note that certain device types enforce pools allocated at | ||
| 176 | * fixed size (frame count), which cannot be extended dynamically. In such a | ||
| 177 | * case, initial_pool_size must be set appropriately. | ||
| 178 | */ | ||
| 179 | AVBufferPool *pool; | ||
| 180 | |||
| 181 | /** | ||
| 182 | * Initial size of the frame pool. If a device type does not support | ||
| 183 | * dynamically resizing the pool, then this is also the maximum pool size. | ||
| 184 | * | ||
| 185 | * May be set by the caller before calling av_hwframe_ctx_init(). Must be | ||
| 186 | * set if pool is NULL and the device type does not support dynamic pools. | ||
| 187 | */ | ||
| 188 | int initial_pool_size; | ||
| 189 | |||
| 190 | /** | ||
| 191 | * The pixel format identifying the underlying HW surface type. | ||
| 192 | * | ||
| 193 | * Must be a hwaccel format, i.e. the corresponding descriptor must have the | ||
| 194 | * AV_PIX_FMT_FLAG_HWACCEL flag set. | ||
| 195 | * | ||
| 196 | * Must be set by the user before calling av_hwframe_ctx_init(). | ||
| 197 | */ | ||
| 198 | enum AVPixelFormat format; | ||
| 199 | |||
| 200 | /** | ||
| 201 | * The pixel format identifying the actual data layout of the hardware | ||
| 202 | * frames. | ||
| 203 | * | ||
| 204 | * Must be set by the caller before calling av_hwframe_ctx_init(). | ||
| 205 | * | ||
| 206 | * @note when the underlying API does not provide the exact data layout, but | ||
| 207 | * only the colorspace/bit depth, this field should be set to the fully | ||
| 208 | * planar version of that format (e.g. for 8-bit 420 YUV it should be | ||
| 209 | * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else). | ||
| 210 | */ | ||
| 211 | enum AVPixelFormat sw_format; | ||
| 212 | |||
| 213 | /** | ||
| 214 | * The allocated dimensions of the frames in this pool. | ||
| 215 | * | ||
| 216 | * Must be set by the user before calling av_hwframe_ctx_init(). | ||
| 217 | */ | ||
| 218 | int width, height; | ||
| 219 | } AVHWFramesContext; | ||
| 220 | |||
| 221 | /** | ||
| 222 | * Allocate an AVHWDeviceContext for a given pixel format. | ||
| 223 | * | ||
| 224 | * @param format a hwaccel pixel format (AV_PIX_FMT_FLAG_HWACCEL must be set | ||
| 225 | * on the corresponding format descriptor) | ||
| 226 | * @return a reference to the newly created AVHWDeviceContext on success or NULL | ||
| 227 | * on failure. | ||
| 228 | */ | ||
| 229 | AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type); | ||
| 230 | |||
| 231 | /** | ||
| 232 | * Finalize the device context before use. This function must be called after | ||
| 233 | * the context is filled with all the required information and before it is | ||
| 234 | * used in any way. | ||
| 235 | * | ||
| 236 | * @param ref a reference to the AVHWDeviceContext | ||
| 237 | * @return 0 on success, a negative AVERROR code on failure | ||
| 238 | */ | ||
| 239 | int av_hwdevice_ctx_init(AVBufferRef *ref); | ||
| 240 | |||
| 241 | /** | ||
| 242 | * Allocate an AVHWFramesContext tied to a given device context. | ||
| 243 | * | ||
| 244 | * @param device_ctx a reference to a AVHWDeviceContext. This function will make | ||
| 245 | * a new reference for internal use, the one passed to the | ||
| 246 | * function remains owned by the caller. | ||
| 247 | * @return a reference to the newly created AVHWFramesContext on success or NULL | ||
| 248 | * on failure. | ||
| 249 | */ | ||
| 250 | AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx); | ||
| 251 | |||
| 252 | /** | ||
| 253 | * Finalize the context before use. This function must be called after the | ||
| 254 | * context is filled with all the required information and before it is attached | ||
| 255 | * to any frames. | ||
| 256 | * | ||
| 257 | * @param ref a reference to the AVHWFramesContext | ||
| 258 | * @return 0 on success, a negative AVERROR code on failure | ||
| 259 | */ | ||
| 260 | int av_hwframe_ctx_init(AVBufferRef *ref); | ||
| 261 | |||
| 262 | /** | ||
| 263 | * Allocate a new frame attached to the given AVHWFramesContext. | ||
| 264 | * | ||
| 265 | * @param hwframe_ctx a reference to an AVHWFramesContext | ||
| 266 | * @param frame an empty (freshly allocated or unreffed) frame to be filled with | ||
| 267 | * newly allocated buffers. | ||
| 268 | * @param flags currently unused, should be set to zero | ||
| 269 | * @return 0 on success, a negative AVERROR code on failure | ||
| 270 | */ | ||
| 271 | int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); | ||
| 272 | |||
| 273 | /** | ||
| 274 | * Copy data to or from a hw surface. At least one of dst/src must have an | ||
| 275 | * AVHWFramesContext attached. | ||
| 276 | * | ||
| 277 | * If src has an AVHWFramesContext attached, then the format of dst (if set) | ||
| 278 | * must use one of the formats returned by av_hwframe_transfer_get_formats(src, | ||
| 279 | * AV_HWFRAME_TRANSFER_DIRECTION_FROM). | ||
| 280 | * If dst has an AVHWFramesContext attached, then the format of src must use one | ||
| 281 | * of the formats returned by av_hwframe_transfer_get_formats(dst, | ||
| 282 | * AV_HWFRAME_TRANSFER_DIRECTION_TO) | ||
| 283 | * | ||
| 284 | * dst may be "clean" (i.e. with data/buf pointers unset), in which case the | ||
| 285 | * data buffers will be allocated by this function using av_frame_get_buffer(). | ||
| 286 | * If dst->format is set, then this format will be used, otherwise (when | ||
| 287 | * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. | ||
| 288 | * | ||
| 289 | * @param dst the destination frame. dst is not touched on failure. | ||
| 290 | * @param src the source frame. | ||
| 291 | * @param flags currently unused, should be set to zero | ||
| 292 | * @return 0 on success, a negative AVERROR error code on failure. | ||
| 293 | */ | ||
| 294 | int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags); | ||
| 295 | |||
| 296 | enum AVHWFrameTransferDirection { | ||
| 297 | /** | ||
| 298 | * Transfer the data from the queried hw frame. | ||
| 299 | */ | ||
| 300 | AV_HWFRAME_TRANSFER_DIRECTION_FROM, | ||
| 301 | |||
| 302 | /** | ||
| 303 | * Transfer the data to the queried hw frame. | ||
| 304 | */ | ||
| 305 | AV_HWFRAME_TRANSFER_DIRECTION_TO, | ||
| 306 | }; | ||
| 307 | |||
| 308 | /** | ||
| 309 | * Get a list of possible source or target formats usable in | ||
| 310 | * av_hwframe_transfer_data(). | ||
| 311 | * | ||
| 312 | * @param hwframe_ctx the frame context to obtain the information for | ||
| 313 | * @param dir the direction of the transfer | ||
| 314 | * @param formats the pointer to the output format list will be written here. | ||
| 315 | * The list is terminated with AV_PIX_FMT_NONE and must be freed | ||
| 316 | * by the caller when no longer needed using av_free(). | ||
| 317 | * If this function returns successfully, the format list will | ||
| 318 | * have at least one item (not counting the terminator). | ||
| 319 | * On failure, the contents of this pointer are unspecified. | ||
| 320 | * @param flags currently unused, should be set to zero | ||
| 321 | * @return 0 on success, a negative AVERROR code on failure. | ||
| 322 | */ | ||
| 323 | int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx, | ||
| 324 | enum AVHWFrameTransferDirection dir, | ||
| 325 | enum AVPixelFormat **formats, int flags); | ||
| 326 | |||
| 327 | |||
| 328 | #endif /* AVUTIL_HWCONTEXT_H */ | ||
| @@ -0,0 +1,89 @@ | |||
| 1 | /* | ||
| 2 | * This file is part of Libav. | ||
| 3 | * | ||
| 4 | * Libav is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2.1 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Libav is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Lesser General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||
| 15 | * License along with Libav; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef AVUTIL_HWCONTEXT_INTERNAL_H | ||
| 20 | #define AVUTIL_HWCONTEXT_INTERNAL_H | ||
| 21 | |||
| 22 | #include <stddef.h> | ||
| 23 | |||
| 24 | #include "buffer.h" | ||
| 25 | #include "hwcontext.h" | ||
| 26 | #include "frame.h" | ||
| 27 | #include "pixfmt.h" | ||
| 28 | |||
| 29 | typedef struct HWContextType { | ||
| 30 | enum AVHWDeviceType type; | ||
| 31 | const char *name; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * An array of pixel formats supported by the AVHWFramesContext instances | ||
| 35 | * Terminated by AV_PIX_FMT_NONE. | ||
| 36 | */ | ||
| 37 | const enum AVPixelFormat *pix_fmts; | ||
| 38 | |||
| 39 | /** | ||
| 40 | * size of the public hardware-specific context, | ||
| 41 | * i.e. AVHWDeviceContext.hwctx | ||
| 42 | */ | ||
| 43 | size_t device_hwctx_size; | ||
| 44 | /** | ||
| 45 | * size of the private data, i.e. | ||
| 46 | * AVHWDeviceInternal.priv | ||
| 47 | */ | ||
| 48 | size_t device_priv_size; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * size of the public frame pool hardware-specific context, | ||
| 52 | * i.e. AVHWFramesContext.hwctx | ||
| 53 | */ | ||
| 54 | size_t frames_hwctx_size; | ||
| 55 | /** | ||
| 56 | * size of the private data, i.e. | ||
| 57 | * AVHWFramesInternal.priv | ||
| 58 | */ | ||
| 59 | size_t frames_priv_size; | ||
| 60 | |||
| 61 | int (*device_init)(AVHWDeviceContext *ctx); | ||
| 62 | void (*device_uninit)(AVHWDeviceContext *ctx); | ||
| 63 | |||
| 64 | int (*frames_init)(AVHWFramesContext *ctx); | ||
| 65 | void (*frames_uninit)(AVHWFramesContext *ctx); | ||
| 66 | |||
| 67 | int (*frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame); | ||
| 68 | int (*transfer_get_formats)(AVHWFramesContext *ctx, | ||
| 69 | enum AVHWFrameTransferDirection dir, | ||
| 70 | enum AVPixelFormat **formats); | ||
| 71 | int (*transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst, | ||
| 72 | const AVFrame *src); | ||
| 73 | int (*transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst, | ||
| 74 | const AVFrame *src); | ||
| 75 | } HWContextType; | ||
| 76 | |||
| 77 | struct AVHWDeviceInternal { | ||
| 78 | const HWContextType *hw_type; | ||
| 79 | void *priv; | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct AVHWFramesInternal { | ||
| 83 | const HWContextType *hw_type; | ||
| 84 | void *priv; | ||
| 85 | |||
| 86 | AVBufferPool *pool_internal; | ||
| 87 | }; | ||
| 88 | |||
| 89 | #endif /* AVUTIL_HWCONTEXT_INTERNAL_H */ | ||