1 /*****************************************************************************
2 * qsv.c / qsv.cpp
3 *****************************************************************************
4 * Copyright (C) 2015 L-SMASH Works project
5 *
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
20
21 /* This file is available under an ISC license. */
22
23 #include "cpp_compat.h"
24
25 #include <string.h>
26
27 #ifdef __cplusplus
28 extern "C"
29 {
30 #endif /* __cplusplus */
31 #include <libavcodec/avcodec.h>
32 #include <libavutil/mem.h>
33 #ifdef __cplusplus
34 }
35 #endif /* __cplusplus */
36
37 #include "decode.h"
38
is_qsv_decoder(const AVCodec * codec)39 int is_qsv_decoder
40 (
41 const AVCodec *codec
42 )
43 {
44 if( codec && codec->pix_fmts )
45 for( const enum AVPixelFormat *pix_fmt = codec->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++ )
46 if( *pix_fmt == AV_PIX_FMT_QSV )
47 return 1;
48 return 0;
49 }
50
51 /* Workarounds for Intel QuickSync Video Decoder through libavcodec */
do_qsv_decoder_workaround(AVCodecContext * ctx)52 int do_qsv_decoder_workaround
53 (
54 AVCodecContext *ctx
55 )
56 {
57 ctx->has_b_frames = 16; /* the maximum decoder latency for AVC and HEVC frame */
58 if( ctx->codec_id != AV_CODEC_ID_H264 )
59 return 0;
60 /* Feed an initializer packet to the decoder since libavcodec does not append parameter sets to access units
61 * containing no IDR NAL units. Here we append parameter sets before the fake IDR NAL unit. Without this,
62 * MFXVideoDECODE_DecodeHeader will return MFX_ERR_MORE_DATA. */
63 static const uint8_t fake_idr[] = { 0x00, 0x00, 0x00, 0x01, 0x65 }; /* valid for both start-code and size-field prefixes */
64 int ret = -1;
65 AVPacket initializer;
66 av_init_packet( &initializer );
67 if( ctx->extradata[0] == 1 )
68 {
69 /* Set up the bitstream filter. */
70 AVBSFContext *bsf_ctx = NULL;
71 const AVBitStreamFilter *bsf = av_bsf_get_by_name( "h264_mp4toannexb" );
72 if( !bsf || (ret = av_bsf_alloc( bsf, &bsf_ctx )) < 0 )
73 goto bsf_fail;
74 AVCodecParameters *codecpar = bsf_ctx->par_in;
75 if( (ret = avcodec_parameters_from_context( codecpar, ctx )) < 0 )
76 goto bsf_fail;
77 codecpar->extradata[4] |= 0x03; /* Force 4 byte length size fields. */
78 if( (ret = av_bsf_init( bsf_ctx )) < 0 )
79 goto bsf_fail;
80 /* Convert into AnnexB Byte Stream Format. */
81 uint8_t data[sizeof(fake_idr)];
82 memcpy( data, fake_idr, sizeof(fake_idr) );
83 initializer.data = data;
84 initializer.size = sizeof(fake_idr);
85 AVPacket *in_pkt = &initializer;
86 while( 1 )
87 {
88 if( (ret = av_bsf_send_packet( bsf_ctx, in_pkt )) < 0 )
89 goto bsf_fail;
90 ret = av_bsf_receive_packet( bsf_ctx, &initializer );
91 if( ret == AVERROR( EAGAIN ) || (in_pkt && ret == AVERROR_EOF) )
92 in_pkt = NULL; /* Send a null packet. */
93 else if( ret < 0 )
94 goto bsf_fail;
95 else if( ret == 0 )
96 break;
97 }
98 bsf_fail:
99 /* Tear down the bistream filter. */
100 av_bsf_free( &bsf_ctx );
101 if( ret < 0 )
102 goto fail;
103 }
104 else
105 {
106 if( (ret = av_new_packet( &initializer, ctx->extradata_size + sizeof(fake_idr) )) < 0 )
107 return ret;
108 memcpy( initializer.data, ctx->extradata, ctx->extradata_size );
109 memcpy( initializer.data + ctx->extradata_size, fake_idr, sizeof(fake_idr) );
110 }
111 /* Initialize the decoder. */
112 AVFrame *picture = av_frame_alloc();
113 if( picture )
114 {
115 int got_picture; /* unused */
116 ret = decode_video_packet( ctx, picture, &got_picture, &initializer );
117 av_frame_free( &picture );
118 }
119 fail:
120 av_packet_unref( &initializer );
121 return ret;
122 }
123