Merge commit '772c87c5a658f36d7c0612f5da583fc2bfa54f79'
[ffmpeg.git] / libavcodec / qsvenc.c
1 /*
2  * Intel MediaSDK QSV encoder utility functions
3  *
4  * copyright (c) 2013 Yukinori Yamazoe
5  * copyright (c) 2015 Anton Khirnov
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23
24 #include <string.h>
25 #include <sys/types.h>
26 #include <mfx/mfxvideo.h>
27
28 #include "libavutil/common.h"
29 #include "libavutil/mem.h"
30 #include "libavutil/log.h"
31 #include "libavutil/time.h"
32 #include "libavutil/imgutils.h"
33
34 #include "avcodec.h"
35 #include "internal.h"
36 #include "qsv.h"
37 #include "qsv_internal.h"
38 #include "qsvenc.h"
39
40 static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
41 {
42     const char *ratecontrol_desc;
43
44     float quant;
45     int ret;
46
47     ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
48     if (ret < 0)
49         return AVERROR_BUG;
50     q->param.mfx.CodecId = ret;
51
52     q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16;
53
54     if (avctx->level > 0)
55         q->param.mfx.CodecLevel = avctx->level;
56
57     q->param.mfx.CodecProfile       = q->profile;
58     q->param.mfx.TargetUsage        = q->preset;
59     q->param.mfx.GopPicSize         = FFMAX(0, avctx->gop_size);
60     q->param.mfx.GopRefDist         = FFMAX(-1, avctx->max_b_frames) + 1;
61     q->param.mfx.GopOptFlag         = avctx->flags & AV_CODEC_FLAG_CLOSED_GOP ?
62                                       MFX_GOP_CLOSED : 0;
63     q->param.mfx.IdrInterval        = q->idr_interval;
64     q->param.mfx.NumSlice           = avctx->slices;
65     q->param.mfx.NumRefFrame        = FFMAX(0, avctx->refs);
66     q->param.mfx.EncodedOrder       = 0;
67     q->param.mfx.BufferSizeInKB     = 0;
68
69     q->param.mfx.FrameInfo.FourCC         = MFX_FOURCC_NV12;
70     q->param.mfx.FrameInfo.CropX          = 0;
71     q->param.mfx.FrameInfo.CropY          = 0;
72     q->param.mfx.FrameInfo.CropW          = avctx->width;
73     q->param.mfx.FrameInfo.CropH          = avctx->height;
74     q->param.mfx.FrameInfo.AspectRatioW   = avctx->sample_aspect_ratio.num;
75     q->param.mfx.FrameInfo.AspectRatioH   = avctx->sample_aspect_ratio.den;
76     q->param.mfx.FrameInfo.ChromaFormat   = MFX_CHROMAFORMAT_YUV420;
77     q->param.mfx.FrameInfo.BitDepthLuma   = 8;
78     q->param.mfx.FrameInfo.BitDepthChroma = 8;
79     q->param.mfx.FrameInfo.Width          = FFALIGN(avctx->width, q->width_align);
80
81     if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
82        /* A true field layout (TFF or BFF) is not important here,
83           it will specified later during frame encoding. But it is important
84           to specify is frame progressive or not because allowed heigh alignment
85           does depend by this.
86         */
87         q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
88         q->height_align = 32;
89     } else {
90         q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
91         q->height_align = 16;
92     }
93    q->param.mfx.FrameInfo.Height    = FFALIGN(avctx->height, q->height_align);
94
95     if (avctx->framerate.den > 0 && avctx->framerate.num > 0) {
96         q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num;
97         q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den;
98     } else {
99         q->param.mfx.FrameInfo.FrameRateExtN  = avctx->time_base.den;
100         q->param.mfx.FrameInfo.FrameRateExtD  = avctx->time_base.num;
101     }
102
103     if (avctx->flags & AV_CODEC_FLAG_QSCALE) {
104         q->param.mfx.RateControlMethod = MFX_RATECONTROL_CQP;
105         ratecontrol_desc = "constant quantization parameter (CQP)";
106     } else if (avctx->rc_max_rate == avctx->bit_rate) {
107         q->param.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
108         ratecontrol_desc = "constant bitrate (CBR)";
109     } else if (!avctx->rc_max_rate) {
110 #if QSV_VERSION_ATLEAST(1,7)
111         if (q->look_ahead) {
112             q->param.mfx.RateControlMethod = MFX_RATECONTROL_LA;
113             ratecontrol_desc = "lookahead (LA)";
114         } else
115 #endif
116         {
117             q->param.mfx.RateControlMethod = MFX_RATECONTROL_AVBR;
118             ratecontrol_desc = "average variable bitrate (AVBR)";
119         }
120     } else {
121         q->param.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
122         ratecontrol_desc = "variable bitrate (VBR)";
123     }
124
125     av_log(avctx, AV_LOG_VERBOSE, "Using the %s ratecontrol method\n", ratecontrol_desc);
126
127     switch (q->param.mfx.RateControlMethod) {
128     case MFX_RATECONTROL_CBR:
129     case MFX_RATECONTROL_VBR:
130         q->param.mfx.InitialDelayInKB = avctx->rc_initial_buffer_occupancy / 1000;
131         q->param.mfx.TargetKbps       = avctx->bit_rate / 1000;
132         q->param.mfx.MaxKbps          = avctx->rc_max_rate / 1000;
133         break;
134     case MFX_RATECONTROL_CQP:
135         quant = avctx->global_quality / FF_QP2LAMBDA;
136
137         q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
138         q->param.mfx.QPP = av_clip(quant, 0, 51);
139         q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);
140
141         break;
142     case MFX_RATECONTROL_AVBR:
143 #if QSV_VERSION_ATLEAST(1,7)
144     case MFX_RATECONTROL_LA:
145 #endif
146         q->param.mfx.TargetKbps  = avctx->bit_rate / 1000;
147         q->param.mfx.Convergence = q->avbr_convergence;
148         q->param.mfx.Accuracy    = q->avbr_accuracy;
149         break;
150     }
151
152     // the HEVC encoder plugin currently fails if coding options
153     // are provided
154     if (avctx->codec_id != AV_CODEC_ID_HEVC) {
155         q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
156         q->extco.Header.BufferSz      = sizeof(q->extco);
157         q->extco.CAVLC                = avctx->coder_type == FF_CODER_TYPE_VLC ?
158                                         MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
159
160         q->extco.PicTimingSEI         = q->pic_timing_sei ?
161                                         MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
162
163         q->extparam_internal[0] = (mfxExtBuffer *)&q->extco;
164
165 #if QSV_VERSION_ATLEAST(1,6)
166         q->extco2.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION2;
167         q->extco2.Header.BufferSz      = sizeof(q->extco2);
168
169 #if QSV_VERSION_ATLEAST(1,7)
170         // valid value range is from 10 to 100 inclusive
171         // to instruct the encoder to use the default value this should be set to zero
172         q->extco2.LookAheadDepth        = q->look_ahead_depth != 0 ? FFMAX(10, q->look_ahead_depth) : 0;
173 #endif
174 #if QSV_VERSION_ATLEAST(1,8)
175         q->extco2.LookAheadDS           = q->look_ahead_downsampling;
176 #endif
177
178         q->extparam_internal[1] = (mfxExtBuffer *)&q->extco2;
179
180 #endif
181     }
182
183     return 0;
184 }
185
186 static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
187 {
188     uint8_t sps_buf[128];
189     uint8_t pps_buf[128];
190
191     mfxExtCodingOptionSPSPPS extradata = {
192         .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
193         .Header.BufferSz = sizeof(extradata),
194         .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
195         .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
196     };
197
198     mfxExtBuffer *ext_buffers[] = {
199         (mfxExtBuffer*)&extradata,
200     };
201
202     int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
203     int ret;
204
205     q->param.ExtParam    = ext_buffers;
206     q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers);
207
208     ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
209     if (ret < 0)
210         return ff_qsv_error(ret);
211
212     q->packet_size = q->param.mfx.BufferSizeInKB * 1000;
213
214     if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) {
215         av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
216         return AVERROR_UNKNOWN;
217     }
218
219     avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize +
220                                  AV_INPUT_BUFFER_PADDING_SIZE);
221     if (!avctx->extradata)
222         return AVERROR(ENOMEM);
223
224     memcpy(avctx->extradata,                        sps_buf, extradata.SPSBufSize);
225     if (need_pps)
226         memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize);
227     avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize;
228     memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
229
230     return 0;
231 }
232
233 int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
234 {
235     int ret;
236
237     q->param.IOPattern  = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
238     q->param.AsyncDepth = q->async_depth;
239
240     q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
241                                   (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*)));
242     if (!q->async_fifo)
243         return AVERROR(ENOMEM);
244
245     if (avctx->hwaccel_context) {
246         AVQSVContext *qsv = avctx->hwaccel_context;
247
248         q->session         = qsv->session;
249         q->param.IOPattern = qsv->iopattern;
250     }
251
252     if (!q->session) {
253         ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
254                                            q->load_plugins);
255         if (ret < 0)
256             return ret;
257
258         q->session = q->internal_qs.session;
259     }
260
261     ret = init_video_param(avctx, q);
262     if (ret < 0)
263         return ret;
264
265     ret = MFXVideoENCODE_Query(q->session, &q->param,&q->param);
266     if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
267         av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
268     } else if (ret < 0) {
269         av_log(avctx, AV_LOG_ERROR, "Error %d querying encoder params\n", ret);
270         return ff_qsv_error(ret);
271     }
272
273     ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
274     if (ret < 0) {
275         av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
276         return ff_qsv_error(ret);
277     }
278
279     if (avctx->hwaccel_context) {
280         AVQSVContext *qsv = avctx->hwaccel_context;
281         int i, j;
282
283         q->extparam = av_mallocz_array(qsv->nb_ext_buffers + FF_ARRAY_ELEMS(q->extparam_internal),
284                                        sizeof(*q->extparam));
285         if (!q->extparam)
286             return AVERROR(ENOMEM);
287
288         q->param.ExtParam = q->extparam;
289         for (i = 0; i < qsv->nb_ext_buffers; i++)
290             q->param.ExtParam[i] = qsv->ext_buffers[i];
291         q->param.NumExtParam = qsv->nb_ext_buffers;
292
293         for (i = 0; i < FF_ARRAY_ELEMS(q->extparam_internal); i++) {
294             for (j = 0; j < qsv->nb_ext_buffers; j++) {
295                 if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId)
296                     break;
297             }
298             if (j < qsv->nb_ext_buffers)
299                 continue;
300
301             q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i];
302         }
303     } else {
304         q->param.ExtParam    = q->extparam_internal;
305         q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam_internal);
306     }
307
308     ret = MFXVideoENCODE_Init(q->session, &q->param);
309     if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
310         av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
311     } else if (ret < 0) {
312         av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
313         return ff_qsv_error(ret);
314     }
315
316     ret = qsv_retrieve_enc_params(avctx, q);
317     if (ret < 0) {
318         av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
319         return ret;
320     }
321
322     q->avctx = avctx;
323
324     return 0;
325 }
326
327 static void clear_unused_frames(QSVEncContext *q)
328 {
329     QSVFrame *cur = q->work_frames;
330     while (cur) {
331         if (cur->surface && !cur->surface->Data.Locked) {
332             cur->surface = NULL;
333             av_frame_unref(cur->frame);
334         }
335         cur = cur->next;
336     }
337 }
338
339 static int get_free_frame(QSVEncContext *q, QSVFrame **f)
340 {
341     QSVFrame *frame, **last;
342
343     clear_unused_frames(q);
344
345     frame = q->work_frames;
346     last  = &q->work_frames;
347     while (frame) {
348         if (!frame->surface) {
349             *f = frame;
350             return 0;
351         }
352
353         last  = &frame->next;
354         frame = frame->next;
355     }
356
357     frame = av_mallocz(sizeof(*frame));
358     if (!frame)
359         return AVERROR(ENOMEM);
360     frame->frame = av_frame_alloc();
361     if (!frame->frame) {
362         av_freep(&frame);
363         return AVERROR(ENOMEM);
364     }
365     *last = frame;
366
367     *f = frame;
368
369     return 0;
370 }
371
372 static int submit_frame(QSVEncContext *q, const AVFrame *frame,
373                         mfxFrameSurface1 **surface)
374 {
375     QSVFrame *qf;
376     int ret;
377
378     ret = get_free_frame(q, &qf);
379     if (ret < 0)
380         return ret;
381
382     if (frame->format == AV_PIX_FMT_QSV) {
383         ret = av_frame_ref(qf->frame, frame);
384         if (ret < 0)
385             return ret;
386
387         qf->surface = (mfxFrameSurface1*)qf->frame->data[3];
388         *surface = qf->surface;
389         return 0;
390     }
391
392     /* make a copy if the input is not padded as libmfx requires */
393     if (     frame->height & (q->height_align - 1) ||
394         frame->linesize[0] & (q->width_align - 1)) {
395         qf->frame->height = FFALIGN(frame->height, q->height_align);
396         qf->frame->width  = FFALIGN(frame->width, q->width_align);
397
398         ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
399         if (ret < 0)
400             return ret;
401
402         qf->frame->height = frame->height;
403         qf->frame->width  = frame->width;
404         ret = av_frame_copy(qf->frame, frame);
405         if (ret < 0) {
406             av_frame_unref(qf->frame);
407             return ret;
408         }
409     } else {
410         ret = av_frame_ref(qf->frame, frame);
411         if (ret < 0)
412             return ret;
413     }
414
415     qf->surface_internal.Info = q->param.mfx.FrameInfo;
416
417     qf->surface_internal.Info.PicStruct =
418         !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
419         frame->top_field_first   ? MFX_PICSTRUCT_FIELD_TFF :
420                                    MFX_PICSTRUCT_FIELD_BFF;
421     if (frame->repeat_pict == 1)
422         qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
423     else if (frame->repeat_pict == 2)
424         qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
425     else if (frame->repeat_pict == 4)
426         qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
427
428     qf->surface_internal.Data.PitchLow  = qf->frame->linesize[0];
429     qf->surface_internal.Data.Y         = qf->frame->data[0];
430     qf->surface_internal.Data.UV        = qf->frame->data[1];
431     qf->surface_internal.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
432
433     qf->surface = &qf->surface_internal;
434
435     *surface = qf->surface;
436
437     return 0;
438 }
439
440 static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
441 {
442     if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
443         if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
444             q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
445             q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
446             av_log(avctx, AV_LOG_WARNING,
447                    "Interlaced coding is supported"
448                    " at Main/High Profile Level 2.1-4.1\n");
449     }
450 }
451
452 int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
453                   AVPacket *pkt, const AVFrame *frame, int *got_packet)
454 {
455     AVPacket new_pkt = { 0 };
456     mfxBitstream *bs;
457
458     mfxFrameSurface1 *surf = NULL;
459     mfxSyncPoint sync      = NULL;
460     int ret;
461
462     if (frame) {
463         ret = submit_frame(q, frame, &surf);
464         if (ret < 0) {
465             av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
466             return ret;
467         }
468     }
469
470     ret = av_new_packet(&new_pkt, q->packet_size);
471     if (ret < 0) {
472         av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n");
473         return ret;
474     }
475
476     bs = av_mallocz(sizeof(*bs));
477     if (!bs) {
478         av_packet_unref(&new_pkt);
479         return AVERROR(ENOMEM);
480     }
481     bs->Data      = new_pkt.data;
482     bs->MaxLength = new_pkt.size;
483
484     do {
485         ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, &sync);
486         if (ret == MFX_WRN_DEVICE_BUSY) {
487             av_usleep(500);
488             continue;
489         }
490         break;
491     } while ( 1 );
492
493     if (ret < 0) {
494         av_packet_unref(&new_pkt);
495         av_freep(&bs);
496         if (ret == MFX_ERR_MORE_DATA)
497             return 0;
498         av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret);
499         return ff_qsv_error(ret);
500     }
501
502     if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) {
503         if (frame->interlaced_frame)
504             print_interlace_msg(avctx, q);
505         else
506             av_log(avctx, AV_LOG_WARNING,
507                    "EncodeFrameAsync returned 'incompatible param' code\n");
508     }
509     if (sync) {
510         av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
511         av_fifo_generic_write(q->async_fifo, &sync,    sizeof(sync),    NULL);
512         av_fifo_generic_write(q->async_fifo, &bs,      sizeof(bs),    NULL);
513     } else {
514         av_packet_unref(&new_pkt);
515         av_freep(&bs);
516     }
517
518     if (!av_fifo_space(q->async_fifo) ||
519         (!frame && av_fifo_size(q->async_fifo))) {
520         av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
521         av_fifo_generic_read(q->async_fifo, &sync,    sizeof(sync),    NULL);
522         av_fifo_generic_read(q->async_fifo, &bs,      sizeof(bs),      NULL);
523
524         MFXVideoCORE_SyncOperation(q->session, sync, 60000);
525
526         new_pkt.dts  = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
527         new_pkt.pts  = av_rescale_q(bs->TimeStamp,       (AVRational){1, 90000}, avctx->time_base);
528         new_pkt.size = bs->DataLength;
529
530         if (bs->FrameType & MFX_FRAMETYPE_IDR ||
531             bs->FrameType & MFX_FRAMETYPE_xIDR)
532             new_pkt.flags |= AV_PKT_FLAG_KEY;
533
534 #if FF_API_CODED_FRAME
535 FF_DISABLE_DEPRECATION_WARNINGS
536         if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI)
537             avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
538         else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP)
539             avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
540         else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB)
541             avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
542 FF_ENABLE_DEPRECATION_WARNINGS
543 #endif
544
545         av_freep(&bs);
546
547         if (pkt->data) {
548             if (pkt->size < new_pkt.size) {
549                 av_log(avctx, AV_LOG_ERROR, "Submitted buffer not large enough: %d < %d\n",
550                        pkt->size, new_pkt.size);
551                 av_packet_unref(&new_pkt);
552                 return AVERROR(EINVAL);
553             }
554
555             memcpy(pkt->data, new_pkt.data, new_pkt.size);
556             pkt->size = new_pkt.size;
557
558             ret = av_packet_copy_props(pkt, &new_pkt);
559             av_packet_unref(&new_pkt);
560             if (ret < 0)
561                 return ret;
562         } else
563             *pkt = new_pkt;
564
565         *got_packet = 1;
566     }
567
568     return 0;
569 }
570
571 int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
572 {
573     QSVFrame *cur;
574
575     if (q->session)
576         MFXVideoENCODE_Close(q->session);
577     q->session = NULL;
578
579     ff_qsv_close_internal_session(&q->internal_qs);
580
581     cur = q->work_frames;
582     while (cur) {
583         q->work_frames = cur->next;
584         av_frame_free(&cur->frame);
585         av_freep(&cur);
586         cur = q->work_frames;
587     }
588
589     while (q->async_fifo && av_fifo_size(q->async_fifo)) {
590         AVPacket pkt;
591         mfxSyncPoint sync;
592         mfxBitstream *bs;
593
594         av_fifo_generic_read(q->async_fifo, &pkt,  sizeof(pkt),  NULL);
595         av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
596         av_fifo_generic_read(q->async_fifo, &bs,   sizeof(bs),   NULL);
597
598         av_freep(&bs);
599         av_packet_unref(&pkt);
600     }
601     av_fifo_free(q->async_fifo);
602     q->async_fifo = NULL;
603
604     av_freep(&q->extparam);
605
606     return 0;
607 }