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