hwcontext_mediacodec.c (3553B)
1 /* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 <android/native_window.h> 22 #include <dlfcn.h> 23 #include <media/NdkMediaCodec.h> 24 25 #include "buffer.h" 26 #include "common.h" 27 #include "hwcontext.h" 28 #include "hwcontext_internal.h" 29 #include "hwcontext_mediacodec.h" 30 31 typedef struct MediaCodecDeviceContext { 32 AVMediaCodecDeviceContext ctx; 33 34 void *libmedia; 35 media_status_t (*create_surface)(ANativeWindow **surface); 36 } MediaCodecDeviceContext; 37 38 39 static int mc_device_create(AVHWDeviceContext *ctx, const char *device, 40 AVDictionary *opts, int flags) 41 { 42 const AVDictionaryEntry *entry = NULL; 43 MediaCodecDeviceContext *s = ctx->hwctx; 44 AVMediaCodecDeviceContext *dev = &s->ctx; 45 46 if (device && device[0]) { 47 av_log(ctx, AV_LOG_ERROR, "Device selection unsupported.\n"); 48 return AVERROR_UNKNOWN; 49 } 50 51 while ((entry = av_dict_iterate(opts, entry))) { 52 if (!strcmp(entry->key, "create_window")) 53 dev->create_window = atoi(entry->value); 54 } 55 56 av_log(ctx, AV_LOG_DEBUG, "%s createPersistentInputSurface\n", 57 dev->create_window ? "Enable" : "Disable"); 58 59 return 0; 60 } 61 62 static int mc_device_init(AVHWDeviceContext *ctx) 63 { 64 MediaCodecDeviceContext *s = ctx->hwctx; 65 AVMediaCodecDeviceContext *dev = (AVMediaCodecDeviceContext *)s; 66 ANativeWindow *native_window = NULL; 67 68 if (dev->surface) 69 return 0; 70 71 if (dev->native_window) 72 return 0; 73 74 // For backward compatibility, don't return error for a dummy 75 // AVHWDeviceContext without surface or native_window. 76 if (!dev->create_window) 77 return 0; 78 79 s->libmedia = dlopen("libmediandk.so", RTLD_NOW); 80 if (!s->libmedia) 81 return AVERROR_UNKNOWN; 82 83 s->create_surface = dlsym(s->libmedia, "AMediaCodec_createPersistentInputSurface"); 84 if (!s->create_surface) 85 return AVERROR_UNKNOWN; 86 87 s->create_surface(&native_window); 88 dev->native_window = native_window; 89 return 0; 90 } 91 92 static void mc_device_uninit(AVHWDeviceContext *ctx) 93 { 94 MediaCodecDeviceContext *s = ctx->hwctx; 95 AVMediaCodecDeviceContext *dev = ctx->hwctx; 96 if (!s->libmedia) 97 return; 98 99 if (dev->native_window) { 100 ANativeWindow_release(dev->native_window); 101 dev->native_window = NULL; 102 } 103 dlclose(s->libmedia); 104 s->libmedia = NULL; 105 } 106 107 const HWContextType ff_hwcontext_type_mediacodec = { 108 .type = AV_HWDEVICE_TYPE_MEDIACODEC, 109 .name = "mediacodec", 110 111 .device_hwctx_size = sizeof(MediaCodecDeviceContext), 112 113 .device_create = mc_device_create, 114 .device_init = mc_device_init, 115 .device_uninit = mc_device_uninit, 116 117 .pix_fmts = (const enum AVPixelFormat[]){ 118 AV_PIX_FMT_MEDIACODEC, 119 AV_PIX_FMT_NONE 120 }, 121 };