[FFmpeg-devel] avcodec/cuvid: Use a dummy packet to flush cuvid.

Submitted by Wiki Wang on May 16, 2017, 8:27 a.m.

Details

Message ID SG2PR06MB0601E7AF844D9CC8C638EF0BA0E60@SG2PR06MB0601.apcprd06.prod.outlook.com
State New
Headers show

Commit Message

Wiki Wang May 16, 2017, 8:27 a.m.
---
 libavcodec/cuvid.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

Comments

Timo Rothenpieler May 16, 2017, 8:32 a.m.
Am 16.05.2017 um 10:27 schrieb Wiki Wang:
> ---
>  libavcodec/cuvid.c | 13 +++----------
>  1 file changed, 3 insertions(+), 10 deletions(-)
> 
> diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c
> index 218be8495d..0b1710bd46 100644
> --- a/libavcodec/cuvid.c
> +++ b/libavcodec/cuvid.c
> @@ -1029,20 +1029,13 @@ static void cuvid_flush(AVCodecContext *avctx)
>          return;
>      }
>  
> -    if (ctx->cudecoder) {
> -        ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder);
> -        ctx->cudecoder = NULL;
> -    }
> +    seq_pkt.flags = CUVID_PKT_ENDOFSTREAM;
>  
> -    if (ctx->cuparser) {
> -        ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser);
> -        ctx->cuparser = NULL;
> -    }
> -
> -    ret = CHECK_CU(ctx->cvdl->cuvidCreateVideoParser(&ctx->cuparser, &ctx->cuparseinfo));
> +    ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &seq_pkt));
>      if (ret < 0)
>          goto error;
>  
> +    seq_pkt.flags = 0;
>      seq_pkt.payload = ctx->cuparse_ext.raw_seqhdr_data;
>      seq_pkt.payload_size = ctx->cuparse_ext.format.seqhdr_data_length;
>  
> 

I'm not exactly sure what was the issue for this to be done this way,
but I remember there being some issue with just flushing the decoder,
hence the re-creation.
Philip Langdale May 16, 2017, 1:41 p.m.
On May 16, 2017, at 01:32, Timo Rothenpieler <timo@rothenpieler.org> wrote:
> 
>> Am 16.05.2017 um 10:27 schrieb Wiki Wang:
>> ---
>> libavcodec/cuvid.c | 13 +++----------
>> 1 file changed, 3 insertions(+), 10 deletions(-)
>> 
>> diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c
>> index 218be8495d..0b1710bd46 100644
>> --- a/libavcodec/cuvid.c
>> +++ b/libavcodec/cuvid.c
>> @@ -1029,20 +1029,13 @@ static void cuvid_flush(AVCodecContext *avctx)
>>         return;
>>     }
>> 
>> -    if (ctx->cudecoder) {
>> -        ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder);
>> -        ctx->cudecoder = NULL;
>> -    }
>> +    seq_pkt.flags = CUVID_PKT_ENDOFSTREAM;
>> 
>> -    if (ctx->cuparser) {
>> -        ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser);
>> -        ctx->cuparser = NULL;
>> -    }
>> -
>> -    ret = CHECK_CU(ctx->cvdl->cuvidCreateVideoParser(&ctx->cuparser, &ctx->cuparseinfo));
>> +    ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &seq_pkt));
>>     if (ret < 0)
>>         goto error;
>> 
>> +    seq_pkt.flags = 0;
>>     seq_pkt.payload = ctx->cuparse_ext.raw_seqhdr_data;
>>     seq_pkt.payload_size = ctx->cuparse_ext.format.seqhdr_data_length;
>> 
>> 
> 
> I'm not exactly sure what was the issue for this to be done this way,
> but I remember there being some issue with just flushing the decoder,
> hence the re-creation.
> 
The issue is that when flushing for a media player, you need to drop all
frames in the pipeline too. Inserting EOS means you still have n frames
that will come out after the flush which breaks interactive seeking.

--phil
Hendrik Leppkes May 16, 2017, 2:44 p.m.
On Tue, May 16, 2017 at 3:41 PM, Philip Langdale <philipl@overt.org> wrote:
> On May 16, 2017, at 01:32, Timo Rothenpieler <timo@rothenpieler.org> wrote:
>>
>>> Am 16.05.2017 um 10:27 schrieb Wiki Wang:
>>> ---
>>> libavcodec/cuvid.c | 13 +++----------
>>> 1 file changed, 3 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c
>>> index 218be8495d..0b1710bd46 100644
>>> --- a/libavcodec/cuvid.c
>>> +++ b/libavcodec/cuvid.c
>>> @@ -1029,20 +1029,13 @@ static void cuvid_flush(AVCodecContext *avctx)
>>>         return;
>>>     }
>>>
>>> -    if (ctx->cudecoder) {
>>> -        ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder);
>>> -        ctx->cudecoder = NULL;
>>> -    }
>>> +    seq_pkt.flags = CUVID_PKT_ENDOFSTREAM;
>>>
>>> -    if (ctx->cuparser) {
>>> -        ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser);
>>> -        ctx->cuparser = NULL;
>>> -    }
>>> -
>>> -    ret = CHECK_CU(ctx->cvdl->cuvidCreateVideoParser(&ctx->cuparser, &ctx->cuparseinfo));
>>> +    ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &seq_pkt));
>>>     if (ret < 0)
>>>         goto error;
>>>
>>> +    seq_pkt.flags = 0;
>>>     seq_pkt.payload = ctx->cuparse_ext.raw_seqhdr_data;
>>>     seq_pkt.payload_size = ctx->cuparse_ext.format.seqhdr_data_length;
>>>
>>>
>>
>> I'm not exactly sure what was the issue for this to be done this way,
>> but I remember there being some issue with just flushing the decoder,
>> hence the re-creation.
>>
> The issue is that when flushing for a media player, you need to drop all
> frames in the pipeline too. Inserting EOS means you still have n frames
> that will come out after the flush which breaks interactive seeking.
>

Indeed, flush should be an actual flush - discard all data and start fresh.

It should use the dummy packet "flush" at EOF, we call that operation
"draining" here, the decoder gets called with an empty packet in that
case (if it sets the delay flag, anyway).

- Hendrik

Patch hide | download patch | download mbox

diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c
index 218be8495d..0b1710bd46 100644
--- a/libavcodec/cuvid.c
+++ b/libavcodec/cuvid.c
@@ -1029,20 +1029,13 @@  static void cuvid_flush(AVCodecContext *avctx)
         return;
     }
 
-    if (ctx->cudecoder) {
-        ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder);
-        ctx->cudecoder = NULL;
-    }
+    seq_pkt.flags = CUVID_PKT_ENDOFSTREAM;
 
-    if (ctx->cuparser) {
-        ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser);
-        ctx->cuparser = NULL;
-    }
-
-    ret = CHECK_CU(ctx->cvdl->cuvidCreateVideoParser(&ctx->cuparser, &ctx->cuparseinfo));
+    ret = CHECK_CU(ctx->cvdl->cuvidParseVideoData(ctx->cuparser, &seq_pkt));
     if (ret < 0)
         goto error;
 
+    seq_pkt.flags = 0;
     seq_pkt.payload = ctx->cuparse_ext.raw_seqhdr_data;
     seq_pkt.payload_size = ctx->cuparse_ext.format.seqhdr_data_length;