How can I emulate "-r" switch programmatically?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

How can I emulate "-r" switch programmatically?

wl2776
Administrator
I'm writing an application, remuxing streams.
It has the raw motion jpeg as an input and saves it to .avi files.

My problem is that motion jpeg has a frame rate of 2fps, but the resulting files have 25fps.
I know the accurate frame rate value, because all my input frames have timetamps, stored separately.

I have the following code snippet:

in_ioc = avio_alloc_context(< custom IO context routines, input is not a file>);
in_ioc->is_streamed = 1;

input = avformat_alloc_context();
input->pb = in_ioc;
input->iformat = av_find_input_format("mjpeg");
input->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
input->max_analyze->duration = 2 * AV_TIME_BASE;

AVDictionary *options = NULL;
av_dict_set(&options, "s", "704x576", 0);
av_dict_set(&options, "pix_fmt", "yuv420p", 0);
av_dict_set(&options, "r", "2", 0);

avformat_open_input(&input, "input", input->iformat, &options);

av_dict_set(&options, "r", "2", 0);

avformat_find_stream_info(input, &options);

av_dict_free(&options);

av_dump_format(input, 0, "input", 0);

However, av_dump_format anyway writes:
Input #0, mjpeg, from 'input': 
  Duration: N/A, bitrate: N/A
    Stream #0.0: Video: mjpeg, yuvj422p, 704x576, 25 fps, 1200k tbn, 25 tbc

That is, setting framerate to 2 fps had no effect.

However, I've managed to do the same using ffmpeg command line utility.
It writes 2pfs, 2tbr, 1200k tbn, 2 tbc and the resulting videos have correct frame rate.

Here is the full output:
C:\>ffmpeg -y -r 2 -f mjpeg  -i "http://192.168.24.62:15555/copy.cgi?tid=10&mts=1317540591000" -vcodec copy cam2.avi

ffmpeg version N-32962-gcbf914c, Copyright (c) 2000-2011 the FFmpeg developers
  built on Sep 25 2011 21:37:29 with gcc 4.6.1
  configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-runtime-cpudetect --enabl
synth --enable-bzlib --enable-frei0r --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfreetype --e
-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-librtmp --enable-libschroedinger --enable-libspeex --enab
btheora --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-
vs --enable-libxvid --enable-zlib
  libavutil    51. 17. 0 / 51. 17. 0
  libavcodec   53. 17. 0 / 53. 17. 0
  libavformat  53. 13. 0 / 53. 13. 0
  libavdevice  53.  4. 0 / 53.  4. 0
  libavfilter   2. 43. 5 /  2. 43. 5
  libswscale    2.  1. 0 /  2.  1. 0
  libpostproc  51.  2. 0 / 51.  2. 0
[mjpeg @ 003EA040] max_analyze_duration 5000000 reached at 5000000
[mjpeg @ 003EA040] Estimating duration from bitrate, this may be inaccurate
Input #0, mjpeg, from 'http://192.168.24.62:15555/copy.cgi?tid=10&mts=1317540591000':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mjpeg, yuvj422p, 704x576, 2 fps, 2 tbr, 1200k tbn, 2 tbc
Output #0, avi, to 'cam2.avi':
  Metadata:
    ISFT            : Lavf53.13.0
    Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p, 704x576, q=2-31, 4 tbn, 4 tbc
Stream mapping:
  Stream #0.0 -> #0.0 (copy)
Press [q] to stop, [?] for help
frame=  596 fps=164 q=-1.0 Lsize=   19148kB time=00:04:57.75 bitrate= 526.8kbits/s
video:19115kB audio:0kB global headers:0kB muxing overhead 0.176567%
Reply | Threaded
Open this post in threaded view
|

I'll ask in other words - how can I force input frame rate?

wl2776
Administrator
wl2776 wrote
I'm writing an application, remuxing streams.
It has the raw motion jpeg as an input and saves it to .avi files.

My problem is that motion jpeg has a frame rate of 2fps, but the resulting files have 25fps.
I know the accurate frame rate value, because all my input frames have timetamps, stored separately.

I have the following code snippet:

in_ioc = avio_alloc_context(< custom IO context routines, input is not a file>);
in_ioc->is_streamed = 1;

input = avformat_alloc_context();
input->pb = in_ioc;
input->iformat = av_find_input_format("mjpeg");
input->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
input->max_analyze->duration = 2 * AV_TIME_BASE;

AVDictionary *options = NULL;
av_dict_set(&options, "s", "704x576", 0);
av_dict_set(&options, "pix_fmt", "yuv420p", 0);
av_dict_set(&options, "r", "2", 0);

avformat_open_input(&input, "input", input->iformat, &options);

av_dict_set(&options, "r", "2", 0);

avformat_find_stream_info(input, &options);

av_dict_free(&options);

av_dump_format(input, 0, "input", 0);

However, av_dump_format anyway writes:
Input #0, mjpeg, from 'input': 
  Duration: N/A, bitrate: N/A
    Stream #0.0: Video: mjpeg, yuvj422p, 704x576, 25 fps, 1200k tbn, 25 tbc

That is, setting framerate to 2 fps had no effect.

However, I've managed to do the same using ffmpeg command line utility.
It writes 2fps, 2tbr, 1200k tbn, 2 tbc and the resulting videos have correct frame rate.

Here is the full output:
C:\>ffmpeg -y -r 2 -f mjpeg  -i "http://192.168.24.62:15555/copy.cgi?tid=10&mts=1317540591000" -vcodec copy cam2.avi

ffmpeg version N-32962-gcbf914c, Copyright (c) 2000-2011 the FFmpeg developers
  built on Sep 25 2011 21:37:29 with gcc 4.6.1
  configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --enable-runtime-cpudetect --enabl
synth --enable-bzlib --enable-frei0r --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfreetype --e
-libgsm --enable-libmp3lame --enable-libopenjpeg --enable-librtmp --enable-libschroedinger --enable-libspeex --enab
btheora --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-
vs --enable-libxvid --enable-zlib
  libavutil    51. 17. 0 / 51. 17. 0
  libavcodec   53. 17. 0 / 53. 17. 0
  libavformat  53. 13. 0 / 53. 13. 0
  libavdevice  53.  4. 0 / 53.  4. 0
  libavfilter   2. 43. 5 /  2. 43. 5
  libswscale    2.  1. 0 /  2.  1. 0
  libpostproc  51.  2. 0 / 51.  2. 0
[mjpeg @ 003EA040] max_analyze_duration 5000000 reached at 5000000
[mjpeg @ 003EA040] Estimating duration from bitrate, this may be inaccurate
Input #0, mjpeg, from 'http://192.168.24.62:15555/copy.cgi?tid=10&mts=1317540591000':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mjpeg, yuvj422p, 704x576, 2 fps, 2 tbr, 1200k tbn, 2 tbc
Output #0, avi, to 'cam2.avi':
  Metadata:
    ISFT            : Lavf53.13.0
    Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p, 704x576, q=2-31, 4 tbn, 4 tbc
Stream mapping:
  Stream #0.0 -> #0.0 (copy)
Press [q] to stop, [?] for help
frame=  596 fps=164 q=-1.0 Lsize=   19148kB time=00:04:57.75 bitrate= 526.8kbits/s
video:19115kB audio:0kB global headers:0kB muxing overhead 0.176567%
So, it is possible to force input frame rate. How can I do it in my application?
Reply | Threaded
Open this post in threaded view
|

Re: I'll ask in other words - how can I force input frame rate?

Steffen Ebersbach-2
> wl2776 wrote:
>
> So, it is possible to force input frame rate. How can I do it in my
> application?
>

Hello,

in an own application you have to do this resampling by your self. If
you have 2fps input and 25fps output, it means that you have to write
each picture from the input 12,5 times to the output. In fact this is
not possible, so you have to do 12 and 13 pictures for each second. The
code should look like this

- read input sample

while < 12 (13)
     - write to the output
     - wait 40ms

.. and so on

Steffen
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: I'll ask in other words - how can I force input frame rate?

wl2776
Administrator
Steffen Ebersbach-2 wrote
> wl2776 wrote:
>
> So, it is possible to force input frame rate. How can I do it in my
> application?
>

Hello,

in an own application you have to do this resampling by your self. If
you have 2fps input and 25fps output, it means that you have to write
each picture from the input 12,5 times to the output. In fact this is
not possible, so you have to do 12 and 13 pictures for each second. The
code should look like this
Thank you for the answer, but you've misunderstood me.
My problem is that functions avformat_open_input() and avformat_find_stream_info() incorrectly determine frame rate, incorrectly assign values to AVFormatContext/AVStream members (time_base, what else, I don't know) and, since that, av_read_frame returns frames having incorrect PTS/DTS.

I tried using av_rescale_q() to recalculate timestamps, but the resulting value are like the following (dts, pts): (0, 0), (0, 0), (0, 0), (1, 1), (1, 1).

And when I pass the last AVPacket, having pts = dts = 1, to the av_interleaved_write_frame(), it complains that "application has provided non-monotonically increasing timestamps".
Reply | Threaded
Open this post in threaded view
|

Re: I'll ask in other words - how can I force input frame rate?

Steffen Ebersbach-2
Am 10.10.2011 08:54, schrieb wl2776:

> Thank you for the answer, but you've misunderstood me. My problem is
> that functions avformat_open_input() and avformat_find_stream_info()
> incorrectly determine frame rate, incorrectly assign values to
> AVFormatContext/AVStream members (time_base, what else, I don't know)
> and, since that, av_read_frame returns frames having incorrect
> PTS/DTS. I tried using av_rescale_q() to recalculate timestamps, but
> the resulting value are like the following (dts, pts): (0, 0), (0, 0),
> (0, 0), (1, 1), (1, 1). And when I pass the last AVPacket, having pts
> = dts = 1, to the av_interleaved_write_frame(), it complains that
> "application has provided non-monotonically increasing timestamps".

Sry, excuse me.
Now your problem is clear. You write that the timestamps of the mjpeg
frames are stored separately? That means libav don't see them? I think
his is the reason for the wrong entries in avstream/ Fomartcontext. In
this situation the best way i think, ist to manage the pts/dts values by
your self. for mpeg-ts 25fps the right pts are 3600, 7200, ... , because
the time_base is 90000 and the delay is 40 ms.

Steffen

--
Dipl.-Ing.(FH) Steffen Ebersbach
Hochschule Mittweida (FH)
University of Applied Sciences
Forschungsgruppe Optronik
Technikumplatz 17
09648 Mittweida

e-mail [hidden email]
Telefon 03727 58-1113

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: I'll ask in other words - how can I force input frame rate?

wl2776
Administrator
Steffen Ebersbach-2 wrote
Am 10.10.2011 08:54, schrieb wl2776:
> Thank you for the answer, but you've misunderstood me. My problem is
> that functions avformat_open_input() and avformat_find_stream_info()
> incorrectly determine frame rate, incorrectly assign values to
> AVFormatContext/AVStream members (time_base, what else, I don't know)
> and, since that, av_read_frame returns frames having incorrect
> PTS/DTS. I tried using av_rescale_q() to recalculate timestamps, but
> the resulting value are like the following (dts, pts): (0, 0), (0, 0),
> (0, 0), (1, 1), (1, 1). And when I pass the last AVPacket, having pts
> = dts = 1, to the av_interleaved_write_frame(), it complains that
> "application has provided non-monotonically increasing timestamps".

You write that the timestamps of the mjpeg
frames are stored separately? That means libav don't see them? I think
his is the reason for the wrong entries in avstream/ Fomartcontext. In
this situation the best way i think, ist to manage the pts/dts values by
your self. for mpeg-ts 25fps the right pts are 3600, 7200, ... , because
the time_base is 90000 and the delay is 40 ms.
That's right, libav doesn't see timestamps, while my application does.
I'm already going that proposed way, by recalculating timestamps with av_rescale_q().

Now I see that I also can store that separate timestamps in a queue and retrieve them in the main cycle: while (! exit_signaled) { av_read_frame(); ... av_interleaved_write_frame(); }

However, the avformat_find_stream_info() function also reads some data and analyzes the stream basing on them.
I use the results of that analysis to fill the members of output AVFormatContext/AVStream with avcodec_copy_context() and av_metadata_copy();

And I'm unable here to control timestamps, which avformat_find_stream_info() consumes as it is completely opaque to my app.

Therefore I'd like to deliver to libav in the very beginning all the information, my application possesses.
Reply | Threaded
Open this post in threaded view
|

Re: I'll ask in other words - how can I force input frame rate?

wl2776
Administrator
In reply to this post by Steffen Ebersbach-2
Steffen Ebersbach-2 wrote
> wl2776 wrote:
>
> So, it is possible to force input frame rate. How can I do it in my
> application?
>

Hello,

in an own application you have to do this resampling by your self. If
you have 2fps input and 25fps output, it means that you have to write
each picture from the input 12,5 times to the output. In fact this is
not possible, so you have to do 12 and 13 pictures for each second. The
code should look like this

- read input sample

while < 12 (13)
     - write to the output
     - wait 40ms

.. and so on
Sorry for repeating quotes, one more thing, which probably is not obvious.
You can specify "-r" switch (set frame rate) in the command line of ffmpeg *before* "-i" switch.
This makes ffmpeg to consider that *incoming* frame rate is given from outside and it should not neither determine nor assign a default value.
Reply | Threaded
Open this post in threaded view
|

Re: I'll ask in other words - how can I force input frame rate?

Matthew Einhorn
On Mon, Oct 10, 2011 at 3:32 AM, wl2776 <[hidden email]> wrote:

>
> Steffen Ebersbach-2 wrote:
>>
>>> wl2776 wrote:
>>>
>>> So, it is possible to force input frame rate. How can I do it in my
>>> application?
>>>
>>
>> Hello,
>>
>> in an own application you have to do this resampling by your self. If
>> you have 2fps input and 25fps output, it means that you have to write
>> each picture from the input 12,5 times to the output. In fact this is
>> not possible, so you have to do 12 and 13 pictures for each second. The
>> code should look like this
>>
>> - read input sample
>>
>> while < 12 (13)
>>      - write to the output
>>      - wait 40ms
>>
>> .. and so on
>>
>
> Sorry for repeating quotes, one more thing, which probably is not obvious.
> You can specify "-r" switch (set frame rate) in the command line of ffmpeg
> *before* "-i" switch.
> This makes ffmpeg to consider that *incoming* frame rate is given from
> outside and it should not neither determine nor assign a default value.

You might want to look into av_set_string3() in opt.h. I don't know if
it'll help you but you can use it to set stuff like from the command
line.
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user