You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
10KB

  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. #include "config.h"
  19. #include "buffer.h"
  20. #include "common.h"
  21. #include "hwcontext.h"
  22. #include "hwcontext_internal.h"
  23. #include "imgutils.h"
  24. #include "log.h"
  25. #include "mem.h"
  26. #include "pixdesc.h"
  27. #include "pixfmt.h"
  28. static const HWContextType *hw_table[] = {
  29. #if CONFIG_VDPAU
  30. &ff_hwcontext_type_vdpau,
  31. #endif
  32. NULL,
  33. };
  34. static const AVClass hwdevice_ctx_class = {
  35. .class_name = "AVHWDeviceContext",
  36. .item_name = av_default_item_name,
  37. .version = LIBAVUTIL_VERSION_INT,
  38. };
  39. static void hwdevice_ctx_free(void *opaque, uint8_t *data)
  40. {
  41. AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
  42. /* uninit might still want access the hw context and the user
  43. * free() callback might destroy it, so uninit has to be called first */
  44. if (ctx->internal->hw_type->device_uninit)
  45. ctx->internal->hw_type->device_uninit(ctx);
  46. if (ctx->free)
  47. ctx->free(ctx);
  48. av_freep(&ctx->hwctx);
  49. av_freep(&ctx->internal->priv);
  50. av_freep(&ctx->internal);
  51. av_freep(&ctx);
  52. }
  53. AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
  54. {
  55. AVHWDeviceContext *ctx;
  56. AVBufferRef *buf;
  57. const HWContextType *hw_type = NULL;
  58. int i;
  59. for (i = 0; hw_table[i]; i++) {
  60. if (hw_table[i]->type == type) {
  61. hw_type = hw_table[i];
  62. break;
  63. }
  64. }
  65. if (!hw_type)
  66. return NULL;
  67. ctx = av_mallocz(sizeof(*ctx));
  68. if (!ctx)
  69. return NULL;
  70. ctx->internal = av_mallocz(sizeof(*ctx->internal));
  71. if (!ctx->internal)
  72. goto fail;
  73. if (hw_type->device_priv_size) {
  74. ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
  75. if (!ctx->internal->priv)
  76. goto fail;
  77. }
  78. if (hw_type->device_hwctx_size) {
  79. ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
  80. if (!ctx->hwctx)
  81. goto fail;
  82. }
  83. buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
  84. hwdevice_ctx_free, NULL,
  85. AV_BUFFER_FLAG_READONLY);
  86. if (!buf)
  87. goto fail;
  88. ctx->type = type;
  89. ctx->av_class = &hwdevice_ctx_class;
  90. ctx->internal->hw_type = hw_type;
  91. return buf;
  92. fail:
  93. if (ctx->internal)
  94. av_freep(&ctx->internal->priv);
  95. av_freep(&ctx->internal);
  96. av_freep(&ctx->hwctx);
  97. av_freep(&ctx);
  98. return NULL;
  99. }
  100. int av_hwdevice_ctx_init(AVBufferRef *ref)
  101. {
  102. AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
  103. int ret;
  104. if (ctx->internal->hw_type->device_init) {
  105. ret = ctx->internal->hw_type->device_init(ctx);
  106. if (ret < 0)
  107. goto fail;
  108. }
  109. return 0;
  110. fail:
  111. if (ctx->internal->hw_type->device_uninit)
  112. ctx->internal->hw_type->device_uninit(ctx);
  113. return ret;
  114. }
  115. static const AVClass hwframe_ctx_class = {
  116. .class_name = "AVHWFramesContext",
  117. .item_name = av_default_item_name,
  118. .version = LIBAVUTIL_VERSION_INT,
  119. };
  120. static void hwframe_ctx_free(void *opaque, uint8_t *data)
  121. {
  122. AVHWFramesContext *ctx = (AVHWFramesContext*)data;
  123. if (ctx->internal->pool_internal)
  124. av_buffer_pool_uninit(&ctx->internal->pool_internal);
  125. if (ctx->internal->hw_type->frames_uninit)
  126. ctx->internal->hw_type->frames_uninit(ctx);
  127. if (ctx->free)
  128. ctx->free(ctx);
  129. av_buffer_unref(&ctx->device_ref);
  130. av_freep(&ctx->hwctx);
  131. av_freep(&ctx->internal->priv);
  132. av_freep(&ctx->internal);
  133. av_freep(&ctx);
  134. }
  135. AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
  136. {
  137. AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
  138. const HWContextType *hw_type = device_ctx->internal->hw_type;
  139. AVHWFramesContext *ctx;
  140. AVBufferRef *buf, *device_ref = NULL;
  141. ctx = av_mallocz(sizeof(*ctx));
  142. if (!ctx)
  143. return NULL;
  144. ctx->internal = av_mallocz(sizeof(*ctx->internal));
  145. if (!ctx->internal)
  146. goto fail;
  147. if (hw_type->frames_priv_size) {
  148. ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
  149. if (!ctx->internal->priv)
  150. goto fail;
  151. }
  152. if (hw_type->frames_hwctx_size) {
  153. ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
  154. if (!ctx->hwctx)
  155. goto fail;
  156. }
  157. device_ref = av_buffer_ref(device_ref_in);
  158. if (!device_ref)
  159. goto fail;
  160. buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
  161. hwframe_ctx_free, NULL,
  162. AV_BUFFER_FLAG_READONLY);
  163. if (!buf)
  164. goto fail;
  165. ctx->av_class = &hwframe_ctx_class;
  166. ctx->device_ref = device_ref;
  167. ctx->device_ctx = device_ctx;
  168. ctx->format = AV_PIX_FMT_NONE;
  169. ctx->internal->hw_type = hw_type;
  170. return buf;
  171. fail:
  172. if (device_ref)
  173. av_buffer_unref(&device_ref);
  174. if (ctx->internal)
  175. av_freep(&ctx->internal->priv);
  176. av_freep(&ctx->internal);
  177. av_freep(&ctx->hwctx);
  178. av_freep(&ctx);
  179. return NULL;
  180. }
  181. static int hwframe_pool_prealloc(AVBufferRef *ref)
  182. {
  183. AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
  184. AVFrame **frames;
  185. int i, ret = 0;
  186. frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
  187. if (!frames)
  188. return AVERROR(ENOMEM);
  189. for (i = 0; i < ctx->initial_pool_size; i++) {
  190. frames[i] = av_frame_alloc();
  191. if (!frames[i])
  192. goto fail;
  193. ret = av_hwframe_get_buffer(ref, frames[i], 0);
  194. if (ret < 0)
  195. goto fail;
  196. }
  197. fail:
  198. for (i = 0; i < ctx->initial_pool_size; i++)
  199. av_frame_free(&frames[i]);
  200. av_freep(&frames);
  201. return ret;
  202. }
  203. int av_hwframe_ctx_init(AVBufferRef *ref)
  204. {
  205. AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
  206. const enum AVPixelFormat *pix_fmt;
  207. int ret;
  208. /* validate the pixel format */
  209. for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
  210. if (*pix_fmt == ctx->format)
  211. break;
  212. }
  213. if (*pix_fmt == AV_PIX_FMT_NONE) {
  214. av_log(ctx, AV_LOG_ERROR,
  215. "The hardware pixel format '%s' is not supported by the device type '%s'\n",
  216. av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
  217. return AVERROR(ENOSYS);
  218. }
  219. /* validate the dimensions */
  220. ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
  221. if (ret < 0)
  222. return ret;
  223. /* format-specific init */
  224. if (ctx->internal->hw_type->frames_init) {
  225. ret = ctx->internal->hw_type->frames_init(ctx);
  226. if (ret < 0)
  227. goto fail;
  228. }
  229. if (ctx->internal->pool_internal && !ctx->pool)
  230. ctx->pool = ctx->internal->pool_internal;
  231. /* preallocate the frames in the pool, if requested */
  232. if (ctx->initial_pool_size > 0) {
  233. ret = hwframe_pool_prealloc(ref);
  234. if (ret < 0)
  235. goto fail;
  236. }
  237. return 0;
  238. fail:
  239. if (ctx->internal->hw_type->frames_uninit)
  240. ctx->internal->hw_type->frames_uninit(ctx);
  241. return ret;
  242. }
  243. int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
  244. enum AVHWFrameTransferDirection dir,
  245. enum AVPixelFormat **formats, int flags)
  246. {
  247. AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
  248. if (!ctx->internal->hw_type->transfer_get_formats)
  249. return AVERROR(ENOSYS);
  250. return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
  251. }
  252. static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
  253. {
  254. AVFrame *frame_tmp;
  255. int ret = 0;
  256. frame_tmp = av_frame_alloc();
  257. if (!frame_tmp)
  258. return AVERROR(ENOMEM);
  259. /* if the format is set, use that
  260. * otherwise pick the first supported one */
  261. if (dst->format >= 0) {
  262. frame_tmp->format = dst->format;
  263. } else {
  264. enum AVPixelFormat *formats;
  265. ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
  266. AV_HWFRAME_TRANSFER_DIRECTION_FROM,
  267. &formats, 0);
  268. if (ret < 0)
  269. goto fail;
  270. frame_tmp->format = formats[0];
  271. av_freep(&formats);
  272. }
  273. frame_tmp->width = src->width;
  274. frame_tmp->height = src->height;
  275. ret = av_frame_get_buffer(frame_tmp, 32);
  276. if (ret < 0)
  277. goto fail;
  278. ret = av_hwframe_transfer_data(frame_tmp, src, flags);
  279. if (ret < 0)
  280. goto fail;
  281. av_frame_move_ref(dst, frame_tmp);
  282. fail:
  283. av_frame_free(&frame_tmp);
  284. return ret;
  285. }
  286. int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
  287. {
  288. AVHWFramesContext *ctx;
  289. int ret;
  290. if (!dst->buf[0])
  291. return transfer_data_alloc(dst, src, flags);
  292. if (src->hw_frames_ctx) {
  293. ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
  294. ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
  295. if (ret < 0)
  296. return ret;
  297. } else if (dst->hw_frames_ctx) {
  298. ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
  299. ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
  300. if (ret < 0)
  301. return ret;
  302. } else
  303. return AVERROR(ENOSYS);
  304. return 0;
  305. }
  306. int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
  307. {
  308. AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
  309. int ret;
  310. if (!ctx->internal->hw_type->frames_get_buffer)
  311. return AVERROR(ENOSYS);
  312. if (!ctx->pool)
  313. return AVERROR(EINVAL);
  314. frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
  315. if (!frame->hw_frames_ctx)
  316. return AVERROR(ENOMEM);
  317. ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
  318. if (ret < 0) {
  319. av_buffer_unref(&frame->hw_frames_ctx);
  320. return ret;
  321. }
  322. return 0;
  323. }