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.

370 lines
9.9KB

  1. /*
  2. * Intel MediaSDK QSV codec-independent code
  3. *
  4. * copyright (c) 2013 Luca Barbato
  5. * copyright (c) 2015 Anton Khirnov <anton@khirnov.net>
  6. *
  7. * This file is part of Libav.
  8. *
  9. * Libav is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * Libav is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with Libav; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include <string.h>
  24. #include <sys/types.h>
  25. #include <mfx/mfxvideo.h>
  26. #include "libavutil/common.h"
  27. #include "libavutil/mem.h"
  28. #include "libavutil/log.h"
  29. #include "libavutil/pixfmt.h"
  30. #include "libavutil/time.h"
  31. #include "avcodec.h"
  32. #include "internal.h"
  33. #include "qsvdec.h"
  34. int ff_qsv_error(int mfx_err)
  35. {
  36. switch (mfx_err) {
  37. case MFX_ERR_NONE:
  38. return 0;
  39. case MFX_ERR_MEMORY_ALLOC:
  40. case MFX_ERR_NOT_ENOUGH_BUFFER:
  41. return AVERROR(ENOMEM);
  42. case MFX_ERR_INVALID_HANDLE:
  43. return AVERROR(EINVAL);
  44. case MFX_ERR_DEVICE_FAILED:
  45. case MFX_ERR_DEVICE_LOST:
  46. case MFX_ERR_LOCK_MEMORY:
  47. return AVERROR(EIO);
  48. case MFX_ERR_NULL_PTR:
  49. case MFX_ERR_UNDEFINED_BEHAVIOR:
  50. case MFX_ERR_NOT_INITIALIZED:
  51. return AVERROR_BUG;
  52. case MFX_ERR_UNSUPPORTED:
  53. case MFX_ERR_NOT_FOUND:
  54. return AVERROR(ENOSYS);
  55. case MFX_ERR_MORE_DATA:
  56. case MFX_ERR_MORE_SURFACE:
  57. case MFX_ERR_MORE_BITSTREAM:
  58. return AVERROR(EAGAIN);
  59. case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
  60. case MFX_ERR_INVALID_VIDEO_PARAM:
  61. return AVERROR(EINVAL);
  62. case MFX_ERR_ABORTED:
  63. case MFX_ERR_UNKNOWN:
  64. default:
  65. return AVERROR_UNKNOWN;
  66. }
  67. }
  68. int ff_qsv_map_pixfmt(enum AVPixelFormat format)
  69. {
  70. switch (format) {
  71. case AV_PIX_FMT_YUV420P:
  72. case AV_PIX_FMT_YUVJ420P:
  73. return AV_PIX_FMT_NV12;
  74. default:
  75. return AVERROR(ENOSYS);
  76. }
  77. }
  78. static int codec_id_to_mfx(enum AVCodecID codec_id)
  79. {
  80. switch (codec_id) {
  81. case AV_CODEC_ID_H264:
  82. return MFX_CODEC_AVC;
  83. case AV_CODEC_ID_MPEG1VIDEO:
  84. case AV_CODEC_ID_MPEG2VIDEO:
  85. return MFX_CODEC_MPEG2;
  86. case AV_CODEC_ID_VC1:
  87. return MFX_CODEC_VC1;
  88. default:
  89. break;
  90. }
  91. return AVERROR(ENOSYS);
  92. }
  93. static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session)
  94. {
  95. if (!session) {
  96. if (!q->internal_session) {
  97. mfxIMPL impl = MFX_IMPL_AUTO_ANY;
  98. mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
  99. const char *desc;
  100. int ret;
  101. ret = MFXInit(impl, &ver, &q->internal_session);
  102. if (ret < 0) {
  103. av_log(avctx, AV_LOG_ERROR, "Error initializing an internal MFX session\n");
  104. return ff_qsv_error(ret);
  105. }
  106. MFXQueryIMPL(q->internal_session, &impl);
  107. switch (MFX_IMPL_BASETYPE(impl)) {
  108. case MFX_IMPL_SOFTWARE:
  109. desc = "software";
  110. break;
  111. case MFX_IMPL_HARDWARE:
  112. case MFX_IMPL_HARDWARE2:
  113. case MFX_IMPL_HARDWARE3:
  114. case MFX_IMPL_HARDWARE4:
  115. desc = "hardware accelerated";
  116. break;
  117. default:
  118. desc = "unknown";
  119. }
  120. av_log(avctx, AV_LOG_VERBOSE,
  121. "Initialized an internal MFX session using %s implementation\n",
  122. desc);
  123. }
  124. q->session = q->internal_session;
  125. } else {
  126. q->session = session;
  127. }
  128. /* make sure the decoder is uninitialized */
  129. MFXVideoDECODE_Close(q->session);
  130. return 0;
  131. }
  132. int ff_qsv_init(AVCodecContext *avctx, QSVContext *q, mfxSession session)
  133. {
  134. mfxVideoParam param = { { 0 } };
  135. int ret;
  136. ret = qsv_init_session(avctx, q, session);
  137. if (ret < 0) {
  138. av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
  139. return ret;
  140. }
  141. ret = codec_id_to_mfx(avctx->codec_id);
  142. if (ret < 0)
  143. return ret;
  144. param.mfx.CodecId = ret;
  145. param.mfx.CodecProfile = avctx->profile;
  146. param.mfx.CodecLevel = avctx->level;
  147. param.mfx.FrameInfo.BitDepthLuma = 8;
  148. param.mfx.FrameInfo.BitDepthChroma = 8;
  149. param.mfx.FrameInfo.Shift = 0;
  150. param.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
  151. param.mfx.FrameInfo.Width = avctx->coded_width;
  152. param.mfx.FrameInfo.Height = avctx->coded_height;
  153. param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
  154. param.IOPattern = q->iopattern;
  155. param.AsyncDepth = q->async_depth;
  156. param.ExtParam = q->ext_buffers;
  157. param.NumExtParam = q->nb_ext_buffers;
  158. ret = MFXVideoDECODE_Init(q->session, &param);
  159. if (ret < 0) {
  160. av_log(avctx, AV_LOG_ERROR, "Error initializing the MFX video decoder\n");
  161. return ff_qsv_error(ret);
  162. }
  163. return 0;
  164. }
  165. static int alloc_frame(AVCodecContext *avctx, QSVFrame *frame)
  166. {
  167. int ret;
  168. ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF);
  169. if (ret < 0)
  170. return ret;
  171. if (frame->frame->format == AV_PIX_FMT_QSV) {
  172. frame->surface = (mfxFrameSurface1*)frame->frame->data[3];
  173. } else {
  174. frame->surface_internal.Info.BitDepthLuma = 8;
  175. frame->surface_internal.Info.BitDepthChroma = 8;
  176. frame->surface_internal.Info.FourCC = MFX_FOURCC_NV12;
  177. frame->surface_internal.Info.Width = avctx->coded_width;
  178. frame->surface_internal.Info.Height = avctx->coded_height;
  179. frame->surface_internal.Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
  180. frame->surface_internal.Data.PitchLow = frame->frame->linesize[0];
  181. frame->surface_internal.Data.Y = frame->frame->data[0];
  182. frame->surface_internal.Data.UV = frame->frame->data[1];
  183. frame->surface = &frame->surface_internal;
  184. }
  185. return 0;
  186. }
  187. static void qsv_clear_unused_frames(QSVContext *q)
  188. {
  189. QSVFrame *cur = q->work_frames;
  190. while (cur) {
  191. if (cur->surface && !cur->surface->Data.Locked) {
  192. cur->surface = NULL;
  193. av_frame_unref(cur->frame);
  194. }
  195. cur = cur->next;
  196. }
  197. }
  198. static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf)
  199. {
  200. QSVFrame *frame, **last;
  201. int ret;
  202. qsv_clear_unused_frames(q);
  203. frame = q->work_frames;
  204. last = &q->work_frames;
  205. while (frame) {
  206. if (!frame->surface) {
  207. ret = alloc_frame(avctx, frame);
  208. if (ret < 0)
  209. return ret;
  210. *surf = frame->surface;
  211. return 0;
  212. }
  213. last = &frame->next;
  214. frame = frame->next;
  215. }
  216. frame = av_mallocz(sizeof(*frame));
  217. if (!frame)
  218. return AVERROR(ENOMEM);
  219. frame->frame = av_frame_alloc();
  220. if (!frame->frame) {
  221. av_freep(&frame);
  222. return AVERROR(ENOMEM);
  223. }
  224. *last = frame;
  225. ret = alloc_frame(avctx, frame);
  226. if (ret < 0)
  227. return ret;
  228. *surf = frame->surface;
  229. return 0;
  230. }
  231. static AVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
  232. {
  233. QSVFrame *cur = q->work_frames;
  234. while (cur) {
  235. if (surf == cur->surface)
  236. return cur->frame;
  237. cur = cur->next;
  238. }
  239. return NULL;
  240. }
  241. int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q,
  242. AVFrame *frame, int *got_frame,
  243. AVPacket *avpkt)
  244. {
  245. mfxFrameSurface1 *insurf;
  246. mfxFrameSurface1 *outsurf;
  247. mfxSyncPoint sync;
  248. mfxBitstream bs = { { { 0 } } };
  249. int ret;
  250. if (avpkt->size) {
  251. bs.Data = avpkt->data;
  252. bs.DataLength = avpkt->size;
  253. bs.MaxLength = bs.DataLength;
  254. bs.TimeStamp = avpkt->pts;
  255. }
  256. do {
  257. ret = get_surface(avctx, q, &insurf);
  258. if (ret < 0)
  259. return ret;
  260. ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
  261. insurf, &outsurf, &sync);
  262. if (ret == MFX_WRN_DEVICE_BUSY)
  263. av_usleep(1);
  264. } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
  265. if (ret != MFX_ERR_NONE &&
  266. ret != MFX_ERR_MORE_DATA &&
  267. ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
  268. ret != MFX_ERR_MORE_SURFACE) {
  269. av_log(avctx, AV_LOG_ERROR, "Error during QSV decoding.\n");
  270. return ff_qsv_error(ret);
  271. }
  272. if (sync) {
  273. AVFrame *src_frame;
  274. MFXVideoCORE_SyncOperation(q->session, sync, 60000);
  275. src_frame = find_frame(q, outsurf);
  276. if (!src_frame) {
  277. av_log(avctx, AV_LOG_ERROR,
  278. "The returned surface does not correspond to any frame\n");
  279. return AVERROR_BUG;
  280. }
  281. ret = av_frame_ref(frame, src_frame);
  282. if (ret < 0)
  283. return ret;
  284. frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
  285. frame->repeat_pict =
  286. outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
  287. outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
  288. outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
  289. frame->top_field_first =
  290. outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
  291. frame->interlaced_frame =
  292. !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
  293. *got_frame = 1;
  294. }
  295. return bs.DataOffset;
  296. }
  297. int ff_qsv_close(QSVContext *q)
  298. {
  299. QSVFrame *cur = q->work_frames;
  300. while (cur) {
  301. q->work_frames = cur->next;
  302. av_frame_free(&cur->frame);
  303. av_freep(&cur);
  304. cur = q->work_frames;
  305. }
  306. if (q->internal_session)
  307. MFXClose(q->internal_session);
  308. return 0;
  309. }