On 04/09/17 18:01, 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?

Yes: send_frame() is always callable once, and then receive_packet() is 
callable repeatedly until it returns EAGAIN; once it does, send_frame() is 
necessarily callable again.

Can you offer a sequence of valid returns from the lavc API which would break 
it?  (Ignoring what the implementation behind it actually is for a moment.)

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

Reply via email to