summaryrefslogtreecommitdiffstats
path: root/libhb/handbrake/qsv_libav.h
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/handbrake/qsv_libav.h')
-rw-r--r--libhb/handbrake/qsv_libav.h481
1 files changed, 481 insertions, 0 deletions
diff --git a/libhb/handbrake/qsv_libav.h b/libhb/handbrake/qsv_libav.h
new file mode 100644
index 000000000..b74b50c2b
--- /dev/null
+++ b/libhb/handbrake/qsv_libav.h
@@ -0,0 +1,481 @@
+/* ********************************************************************* *\
+
+Copyright (C) 2013 Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+- Neither the name of Intel Corporation nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+\* ********************************************************************* */
+
+#ifndef HB_QSV_LIBAV_H
+#define HB_QSV_LIBAV_H
+
+/**
+ * @file
+ * @ingroup lavc_codec_hwaccel_qsv
+ * Common header for QSV/MediaSDK acceleration
+ */
+
+/**
+ * @defgroup lavc_codec_hwaccel_qsv QSV/MediaSDK based Decode/Encode and VPP
+ * @ingroup lavc_codec_hwaccel
+ *
+ * As Intel Quick Sync Video (QSV) can decode/preprocess/encode with HW
+ * acceleration.
+ *
+ * Supported features:
+ * - access:
+ * - format AV_PIX_FMT_QSV_H264, AVCodec decoder based implementation
+ * - name "h264_qsv", avcodec_find_decoder_by_name( "h264_qsv")
+ * - IO Pattern:
+ * - Opaque memory: MFX_IOPATTERN_OUT_OPAQUE_MEMORY // Video memory is
+ * MFX_IMPL_HARDWARE or MFX_IMPL_AUTO and runtime support,
+ * otherwise: System Memory
+ * - System memory: MFX_IOPATTERN_OUT_SYSTEM_MEMORY
+ * - Allocators:
+ * - default allocator for System memory: MFX_MEMTYPE_SYSTEM_MEMORY
+ * - details:
+ * implementation as "per frame"
+ *
+ * TODO list:
+ * - access:
+ * - format AV_PIX_FMT_QSV_MPEG2
+ * - format AV_PIX_FMT_QSV_VC1
+ * - format AV_PIX_FMT_QSV, see "details" below
+ * - IO Pattern:
+ * - VIDEO_MEMORY // MFX_IOPATTERN_OUT_VIDEO_MEMORY
+ * - Allocators:
+ * - Video memory: MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET /
+ * MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET
+ * - details:
+ * "per slice" support: AV_PIX_FMT_QSV with AVHWAccel based implementation
+ *
+ * Note hb_qsv_config struct required to fill in via
+ * AVCodecContext.hwaccel_context
+ *
+ * As per frame, note AVFrame.data[2] (qsv_atom) used for frame atom id,
+ * data/linesize should be used together with SYSTEM_MEMORY and tested
+ *
+ * Note: Compilation would require:
+ * - Intel MediaSDK headers, Full SDK is available from the original web site:
+ * http://software.intel.com/en-us/vcsource/tools/media-SDK
+ * Will be referenced as mfx*.h (mfxdefs.h, mfxstructures.h, ... )
+ * and
+ * - Final application has to link against Intel MediaSDK dispatcher, available
+ * at MediaSDK as well
+ *
+ * Target OS: as per available dispatcher and driver support
+ *
+ * Implementation details:
+ * Provided struct hb_qsv_context contain several struct hb_qsv_space(s) for decode,
+ * VPP and encode.
+ * hb_qsv_space just contain needed environment for the appropriate action.
+ * Based on this - pipeline (see pipes) will be build to pass details such as
+ * mfxFrameSurface1* and mfxSyncPoint* from one action to the next.
+ *
+ * Resources re-usage (hb_qsv_flush_stages):
+ * hb_qsv_context *qsv = (hb_qsv_context *)video_codec_ctx->priv_data;
+ * hb_qsv_list *pipe = (hb_qsv_list *)video_frame->data[2];
+ * hb_qsv_flush_stages( qsv->pipes, &pipe );
+ *
+ * DTS re-usage:
+ * hb_qsv_dts_pop(qsv);
+ *
+ * for video,DX9/11 memory it has to be Unlock'ed as well
+ *
+ * Implementation is thread aware and uses synchronization point(s) from MediaSDK
+ * as per configuration.
+ *
+ * For the details of MediaSDK usage and options available - please refer to the
+ * available documentation at MediaSDK.
+ *
+ * Feature set used from MSDK is defined by HB_QSV_MSDK_VERSION_MAJOR and
+ * HB_QSV_MSDK_VERSION_MINOR
+ *
+ * @{
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "mfx/mfxvideo.h"
+#include "libavutil/mem.h"
+#include "libavutil/time.h"
+
+#if defined (__GNUC__)
+#include <pthread.h>
+#define ff_qsv_atomic_inc(ptr) __sync_add_and_fetch(ptr,1)
+#define ff_qsv_atomic_dec(ptr) __sync_sub_and_fetch (ptr,1)
+#elif HAVE_WINDOWS_H // MSVC case
+#include <windows.h>
+#if HAVE_PTHREADS
+#include <pthread.h>
+#elif HAVE_W32THREADS
+#include "w32pthreads.h"
+#endif
+#define ff_qsv_atomic_inc(ptr) InterlockedIncrement(ptr)
+#define ff_qsv_atomic_dec(ptr) InterlockedDecrement (ptr)
+#endif
+
+
+// sleep is defined in milliseconds
+#define hb_qsv_sleep(x) av_usleep((x)*1000)
+
+#define HB_QSV_ZERO_MEMORY(VAR) {memset(&VAR, 0, sizeof(VAR));}
+#define HB_QSV_ALIGN32(X) (((mfxU32)((X)+31)) & (~ (mfxU32)31))
+#define HB_QSV_ALIGN16(value) (((value + 15) >> 4) << 4)
+#ifndef HB_QSV_PRINT_RET_MSG
+#define HB_QSV_PRINT_RET_MSG(ERR) { fprintf(stderr, "Error code %d,\t%s\t%d\n", ERR, __FUNCTION__, __LINE__); }
+#endif
+
+#ifndef HB_QSV_DEBUG_ASSERT
+#define HB_QSV_DEBUG_ASSERT(x,y) { if ((x)) { fprintf(stderr, "\nASSERT: %s\n", y); } }
+#endif
+
+#define HB_QSV_CHECK_RET(P, X, ERR) {if ((X) > (P)) {HB_QSV_PRINT_RET_MSG(ERR); return;}}
+#define HB_QSV_CHECK_RESULT(P, X, ERR) {if ((X) > (P)) {HB_QSV_PRINT_RET_MSG(ERR); return ERR;}}
+#define HB_QSV_CHECK_POINTER(P, ERR) {if (!(P)) {HB_QSV_PRINT_RET_MSG(ERR); return ERR;}}
+#define HB_QSV_IGNORE_MFX_STS(P, X) {if ((X) == (P)) {P = MFX_ERR_NONE;}}
+
+#define HB_QSV_ID_BUFFER MFX_MAKEFOURCC('B','U','F','F')
+#define HB_QSV_ID_FRAME MFX_MAKEFOURCC('F','R','M','E')
+
+#define HB_QSV_SURFACE_NUM 80
+#define HB_QSV_SYNC_NUM HB_QSV_SURFACE_NUM*3/4
+#define HB_QSV_BUF_SIZE_DEFAULT 4096*2160*10
+#define HB_QSV_JOB_SIZE_DEFAULT 10
+#define HB_QSV_SYNC_TIME_DEFAULT 10000
+// see hb_qsv_get_free_sync, hb_qsv_get_free_surface , 100 if usleep(10*1000)(10ms) == 1 sec
+#define HB_QSV_REPEAT_NUM_DEFAULT 100
+#define HB_QSV_ASYNC_DEPTH_DEFAULT 4
+
+// version of MSDK/QSV API currently used
+#define HB_QSV_MSDK_VERSION_MAJOR 1
+#define HB_QSV_MSDK_VERSION_MINOR 3
+
+typedef enum HB_QSV_STAGE_TYPE {
+
+#define HB_QSV_DECODE_MASK 0x001
+ HB_QSV_DECODE = 0x001,
+
+#define HB_QSV_VPP_MASK 0x0F0
+ // "Mandatory VPP filter" , might be with "Hint-based VPP filters"
+ HB_QSV_VPP_DEFAULT = 0x010,
+ // "User Modules" etc
+ HB_QSV_VPP_USER = 0x020,
+
+#define av_QSV_ENCODE_MASK 0x100
+ HB_QSV_ENCODE = 0x100
+#define HB_QSV_ANY_MASK 0xFFF
+} HB_QSV_STAGE_TYPE;
+
+
+typedef struct hb_qsv_list {
+ // practically pthread_mutex_t
+ void *mutex;
+ pthread_mutexattr_t mta;
+
+ void **items;
+ int items_alloc;
+
+ int items_count;
+} hb_qsv_list;
+
+typedef struct hb_qsv_sync {
+ mfxSyncPoint* p_sync;
+ int in_use;
+} hb_qsv_sync;
+
+typedef struct hb_qsv_stage {
+ HB_QSV_STAGE_TYPE type;
+ struct {
+ mfxBitstream *p_bs;
+ mfxFrameSurface1 *p_surface;
+ } in;
+ struct {
+ mfxBitstream *p_bs;
+ mfxFrameSurface1 *p_surface;
+ hb_qsv_sync *sync;
+ } out;
+ hb_qsv_list *pending;
+} hb_qsv_stage;
+
+typedef struct hb_qsv_task {
+ mfxBitstream *bs;
+ hb_qsv_stage *stage;
+} hb_qsv_task;
+
+
+typedef struct hb_qsv_space {
+
+ uint8_t is_init_done;
+
+ HB_QSV_STAGE_TYPE type;
+
+ mfxVideoParam m_mfxVideoParam;
+
+ mfxFrameAllocResponse response;
+ mfxFrameAllocRequest request[2]; // [0] - in, [1] - out, if needed
+
+ mfxExtOpaqueSurfaceAlloc ext_opaque_alloc;
+ mfxExtBuffer **p_ext_params;
+ uint16_t p_ext_param_num;
+
+ uint16_t surface_num_max_used;
+ uint16_t surface_num;
+ mfxFrameSurface1 *p_surfaces[HB_QSV_SURFACE_NUM];
+
+ uint16_t sync_num_max_used;
+ uint16_t sync_num;
+ hb_qsv_sync *p_syncp[HB_QSV_SYNC_NUM];
+
+ mfxBitstream bs;
+ uint8_t *p_buf;
+ size_t p_buf_max_size;
+
+ // only for encode and tasks
+ hb_qsv_list *tasks;
+
+ hb_qsv_list *pending;
+
+ // storage for allocations/mfxMemId*
+ mfxMemId *mids;
+} hb_qsv_space;
+
+typedef struct hb_qsv_context {
+ volatile int is_context_active;
+
+ mfxIMPL impl;
+ mfxSession mfx_session;
+ mfxVersion ver;
+
+ // decode
+ hb_qsv_space *dec_space;
+ // encode
+ hb_qsv_space *enc_space;
+ // vpp
+ hb_qsv_list *vpp_space;
+
+ hb_qsv_list *pipes;
+
+ // MediaSDK starting from API version 1.6 includes DecodeTimeStamp
+ // in addition to TimeStamp
+ // see also HB_QSV_MSDK_VERSION_MINOR , HB_QSV_MSDK_VERSION_MAJOR
+ hb_qsv_list *dts_seq;
+
+ // practically pthread_mutex_t
+ void *qts_seq_mutex;
+
+ int is_anex;
+
+ void *qsv_config;
+
+} hb_qsv_context;
+
+typedef enum {
+ QSV_PART_ANY = 0,
+ QSV_PART_LOWER,
+ QSV_PART_UPPER
+} hb_qsv_split;
+
+typedef struct {
+ int64_t dts;
+} hb_qsv_dts;
+
+typedef struct hb_qsv_alloc_frame {
+ mfxU32 id;
+ mfxFrameInfo info;
+} hb_qsv_alloc_frame;
+
+typedef struct hb_qsv_alloc_buffer {
+ mfxU32 id;
+ mfxU32 nbytes;
+ mfxU16 type;
+} hb_qsv_alloc_buffer;
+
+typedef struct hb_qsv_allocators_space {
+ hb_qsv_space *space;
+ mfxFrameAllocator frame_alloc;
+ mfxBufferAllocator buffer_alloc;
+} hb_qsv_allocators_space;
+
+typedef struct hb_qsv_config {
+ /**
+ * Set asynch depth of processing with QSV
+ * Format: 0 and more
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int async_depth;
+
+ /**
+ * Range of numbers that indicate trade-offs between quality and speed.
+ * Format: from 1/MFX_TARGETUSAGE_BEST_QUALITY to 7/MFX_TARGETUSAGE_BEST_SPEED inclusive
+ *
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int target_usage;
+
+ /**
+ * Number of reference frames; if NumRefFrame = 0, this parameter is not specified.
+ * Format: 0 and more
+ *
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int num_ref_frame;
+
+ /**
+ * Distance between I- or P- key frames; if it is zero, the GOP structure is unspecified.
+ * Note: If GopRefDist = 1, there are no B-frames used.
+ *
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int gop_ref_dist;
+
+ /**
+ * Number of pictures within the current GOP (Group of Pictures); if GopPicSize=0,
+ * then the GOP size is unspecified. If GopPicSize=1, only I-frames are used.
+ *
+ * - encoding: Set by user.
+ * - decoding: unused
+ */
+ int gop_pic_size;
+
+ /**
+ * Set type of surfaces used with QSV
+ * Format: "IOPattern enum" of Media SDK
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int io_pattern;
+
+ /**
+ * Set amount of additional surfaces might be needed
+ * Format: amount of additional buffers(surfaces+syncs)
+ * to allocate in advance
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int additional_buffers;
+
+ /**
+ * If pipeline should be sync.
+ * Format: wait time in milliseconds,
+ * HB_QSV_SYNC_TIME_DEFAULT/10000 might be a good value
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int sync_need;
+
+ /**
+ * Type of implementation needed
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int impl_requested;
+
+ /**
+ * if QSV usage is multithreaded.
+ * Format: Yes/No, 1/0
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ int usage_threaded;
+
+ /**
+ * if QSV use an external allocation (valid per session/mfxSession)
+ * Format: pointer to allocators, if default: 0
+ *
+ * note that:
+ * System Memory: can be used without provided and external allocator,
+ * meaning MediaSDK will use an internal one
+ * Video Memory: in this case - we must provide an external allocator
+ * Also, Media SDK session doesn't require external allocator if the application
+ * uses opaque memory
+ *
+ * Calls SetFrameAllocator/SetBufferAllocator
+ * (MFXVideoCORE_SetFrameAllocator/MFXVideoCORE_SetBufferAllocator)
+ * are to pass allocators to Media SDK
+ *
+ * - encoding: Set by user.
+ * - decoding: Set by user.
+ */
+ hb_qsv_allocators_space *allocators;
+
+} hb_qsv_config;
+
+#define ANEX_UNKNOWN 0
+#define ANEX_PREFIX 1
+#define ANEX_NO_PREFIX 2
+
+static const uint8_t ff_prefix_code[] = { 0x00, 0x00, 0x00, 0x01 };
+
+int hb_qsv_get_free_sync(hb_qsv_space *, hb_qsv_context *);
+int hb_qsv_get_free_surface(hb_qsv_space *, hb_qsv_context *, mfxFrameInfo *,
+ hb_qsv_split);
+int hb_qsv_get_free_encode_task(hb_qsv_list *);
+
+int av_is_qsv_available(mfxIMPL, mfxVersion *);
+void hb_qsv_wait_on_sync(hb_qsv_context *, hb_qsv_stage *);
+
+void hb_qsv_add_context_usage(hb_qsv_context *, int);
+
+void hb_qsv_pipe_list_create(hb_qsv_list **, int);
+void hb_qsv_pipe_list_clean(hb_qsv_list **);
+
+void hb_qsv_add_stagee(hb_qsv_list **, hb_qsv_stage *, int);
+hb_qsv_stage *hb_qsv_get_last_stage(hb_qsv_list *);
+hb_qsv_list *hb_qsv_pipe_by_stage(hb_qsv_list *, hb_qsv_stage *);
+void hb_qsv_flush_stages(hb_qsv_list *, hb_qsv_list **);
+
+void hb_qsv_dts_ordered_insert(hb_qsv_context *, int, int, int64_t, int);
+void hb_qsv_dts_pop(hb_qsv_context *);
+
+hb_qsv_stage *hb_qsv_stage_init(void);
+void hb_qsv_stage_clean(hb_qsv_stage **);
+int hb_qsv_context_clean(hb_qsv_context *);
+
+int ff_qsv_is_sync_in_pipe(mfxSyncPoint *, hb_qsv_context *);
+int ff_qsv_is_surface_in_pipe(mfxFrameSurface1 *, hb_qsv_context *);
+
+hb_qsv_list *hb_qsv_list_init(int);
+int hb_qsv_list_lock(hb_qsv_list *);
+int hb_qsv_list_unlock(hb_qsv_list *);
+int hb_qsv_list_add(hb_qsv_list *, void *);
+void hb_qsv_list_rem(hb_qsv_list *, void *);
+void hb_qsv_list_insert(hb_qsv_list *, int, void *);
+void hb_qsv_list_close(hb_qsv_list **);
+
+int hb_qsv_list_count(hb_qsv_list *);
+void *hb_qsv_list_item(hb_qsv_list *, int);
+
+/* @} */
+
+#endif // HB_QSV_LIBAV_H