On 04/09/17 18:16, Jorge Ramirez wrote:
> On 09/04/2017 07:01 PM, Jorge Ramirez wrote:
>> On 09/04/2017 06:31 PM, Mark Thompson wrote:
>>> On 04/09/17 17:00, Jorge Ramirez wrote:
>>>> On 09/03/2017 08:23 PM, Mark Thompson wrote:
>>>>> On 03/09/17 17:54, Jorge Ramirez wrote:
>>>>>> On 09/03/2017 02:27 AM, Mark Thompson wrote:
>>>>>>>> +/* in ffmpeg there is a single thread could be queueing/dequeuing 
>>>>>>>> buffers so a
>>>>>>>> + * timeout is * required when retrieving a frame in case the driver 
>>>>>>>> has not received
>>>>>>>> + * enough input * to start generating output.
>>>>>>>> + *
>>>>>>>> + * once decoding starts, the timeout should not be hit.
>>>>>>> This seems like it could introduce a significant delay on startup for 
>>>>>>> no good reason.  Can you instead just queue packets until either you 
>>>>>>> run out of input buffers or a nonblocking dequeue succeeds?
>>>>>>>
>>>>>>> (I might need to think more about how the semantics of this work.)
>>>>>>>
>>>>>> if the decoder needs 4 blocks, the delay is 200ms, if it is 10 blocks, 
>>>>>> that is 500ms which doesn't seem too significant? when I test I barely 
>>>>>> notice the difference with respect to using the h264 codec (or any of 
>>>>>> the others in fact)
>>>>>>
>>>>>> the best solution would be to be able to block until the capture queue 
>>>>>> has frames ready but for that we would need another thread inputting 
>>>>>> independently on the other queue...does ffmpeg allow for this? separate 
>>>>>> threads for input and output?
>>>>> Since the API is nonblocking, you can just return EAGAIN from 
>>>>> receive_frame if there are any free buffers (to request more input).  You 
>>>>> would then only block waiting for output if there is no more input (end 
>>>>> of stream) or there aren't any free buffers (so no more input could be 
>>>>> accepted). Ideally there would then be no timeouts at all except in error 
>>>>> cases.
>>>> sure, can do that as well, not a problem.
>>>>
>>>> the encoding API doesnt seem to allow for this though: once it retrieves a 
>>>> valid frame it appears to keep on reading them without inputing others 
>>>> (this causes teh capture queue to block for ever)
>>>>
>>>> is this intentional or is it a bug?
>>> The encode API should be identical to the decode API with frames/packets 
>>> swapped (see docs in avcodec.h).
>>>
>>> If you have an lavc-using program which calls receive_packet() repeatedly 
>>> after it has returned EAGAIN and never calls send_packet() then that 
>>> program is wrong.
>>
>> thanks for the prompt answer.
>>
>> yes I am just using the ffmpeg binary to encode a stream; however once a 
>> valid encoded packet is returned,  send_frame is not ever called again 
>> unless I return EAGAIN from v4l2m2m_receive_packet.
>> But I cant return EAGAIN on receive_packet while I am blocked waiting for 
>> data which will never arrive (since send_frame is not executing)
>>
>> seems to me like a bug in ffmeg but I dont like to question baseline code 
>> with obvious bugs (this seems to simple to be real)
>>
>> anyway looking at the function do_video_out() the code seems strange but it 
>> explains why my encoding blocks unless I timeout and return EAGAIN.
>>
>>
>>         ret = avcodec_send_frame(enc, in_picture);
>>         if (ret < 0)
>>             goto error;
>>
>>         while (1) {
>>             ret = avcodec_receive_packet(enc, &pkt);
>>             update_benchmark("encode_video %d.%d", ost->file_index, 
>> ost->index);
>>             if (ret == AVERROR(EAGAIN))
>>                 break;
>>             if (ret < 0)
>>                 goto error;
>>
>>             if (debug_ts) {
>>                 av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
>>                        "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s 
>> pkt_dts_time:%s\n",
>>                        av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, 
>> &enc->time_base),
>>                        av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, 
>> &enc->time_base));
>>             }
>>
>>             if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & 
>> AV_CODEC_CAP_DELAY))
>>                 pkt.pts = ost->sync_opts;
>>
>>             av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase);
>>
>>             if (debug_ts) {
>>                 av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
>>                     "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s 
>> pkt_dts_time:%s\n",
>>                     av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, 
>> &ost->mux_timebase),
>>                     av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, 
>> &ost->mux_timebase));
>>             }
>>
>>             frame_size = pkt.size;
>>             output_packet(of, &pkt, ost, 0);
>>
>>             /* if two pass, output log */
>>             if (ost->logfile && enc->stats_out) {
>>                 fprintf(ost->logfile, "%s", enc->stats_out);
>>             }
>>         }
>>     }
>>
>>
>> so if I queue 20 frames in the output queue and the allow frames to be 
>> dequeued, all of them are dequeued at once and then the code just blocks 
>> waiting for more input...
>>
>>
>>
>> does the above look ok to you?
> 
> this patch allows me to remove the timeout on encode..
> 
> diff --git a/ffmpeg.c b/ffmpeg.c
> index ccb6638..57db03a 100644
> --- a/ffmpeg.c
> +++ b/ffmpeg.c
> @@ -1323,6 +1323,9 @@ static void do_video_out(OutputFile *of,
>              if (ost->logfile && enc->stats_out) {
>                  fprintf(ost->logfile, "%s", enc->stats_out);
>              }
> +
> +            ret = AVERROR(EAGAIN);
> +            break;
>          }
>      }
>      ost->sync_opts++;
> 

It's also wrong, because send_frame() need not be successfully callable until 
receive_packet() has returned EAGAIN.  If you get to this added case then it 
hasn't, so the send_frame() might fail with EAGAIN which is not allowed by the 
code (it was calling receive_packet() repeatedly to ensure that send_frame() 
will be callable next time).

- Mark
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to