Hi all,

On 2009-08-03 at 00:28:43 [+0200], Stephan Assmus <[email protected]> 
wrote:
> I've searched the list archives and googled a bit for my problem, but 
> didn't find anything that makes sense to me.
> 
> I am trying to encode one video and one audio stream into an AVI. The 
> video is H264 at 25 fps and the audio is raw 16bit PCM at 44100 Hz. The 
> actual encoding goes fine and the file plays back, but there is a severe 
> confusion about the time_base of the audio stream which messes up the 
> final duration of the file (actually only the audio stream).
> 
> I am filling out all the time_base fields. My first question would be why 
> there are two time_base fields, one in the AVStream structure and then 
> another one in the AVCodecContext structure (AVStream->codec). I've 
> looked a bit at the av_write_header() function, and I don't get it at 
> all. For example, there is code like this:
> 
>     /* init PTS generation */
>     for(i=0;i<s->nb_streams;i++) {
>         int64_t den = AV_NOPTS_VALUE;
>         st = s->streams[i];
> 
>         switch (st->codec->codec_type) {
>         case CODEC_TYPE_AUDIO:
>             den = (int64_t)st->time_base.num * st->codec->sample_rate; 
>             break;
>         case CODEC_TYPE_VIDEO:
>             den = (int64_t)st->time_base.num * st->codec->time_base.den; 
>             break;
>         default:
>             break;
>         }
>         if (den != AV_NOPTS_VALUE) {
>             if (den <= 0)
>                 return AVERROR_INVALIDDATA;
>             av_frac_init(&st->pts, 0, 0, den);
>         }
>     }
> 
> So it uses time_base.num from AVStream, and time_base.den from 
> AVStream->codec for vieo streams?
> 
> 
> In any case, what happens is that I set the audio stream timebase to 
> "1/44100", both in AVStream and AVStream->codec. Additionally, I set 
> sample_rate to 44100.
> 
> After calling av_write_header(), the AVStream time_base has magically 
> changed to 1/2000. I have no idea where that comes from. It seems to be 
> the AVI muxer doing it, since when I comment out the call to 
> write_header() of the muxer in av_write_header(), it doesn't change. From 
> looking at the AVI code, I don't see where it happens.
> 
> Anyways, when I prepare the audio packets, I calculate the PTS like this:
> 
>     fPacket.pts = (encodeInfo->start_time
>         * fStream->time_base.den / fStream->time_base.num) / 1000000;
> 
> encodeInfo->start_time is the chunk start time relative to the stream 
> start (0) in 1/1000000 seconds. fStream is the AVStream structure.
> 
> So what happens is that even though the time_base changed, I should still 
> be calculating the PTS correctly. The problem is that 
> AVStream->codec->time_base was not adjusted. It's still 1/44100. The 
> resulting file reports a much too long duration as a result. I've 
> calculated that the reported duration pts is correct for a 1/44100 
> timebase, but of course the reported AVStream time_base when I open the 
> file is 1/2000.
> 
> The interesting thing is that when I do not set any of the time_base 
> values for audio streams, but only the sample rate, the same thing 
> happens. Initially, the stream has 1/90000, the codec has 0/1 and after 
> calling av_write_header, the stream is 1/2000, codec still 0/1, but the 
> resulting file reports a wrong duration for the audio stream (would fit 
> for 1/44100).
> 
> What am I doing wrong? :-) Am I even supposed to calculate the packet PTS 
> which I pass to av_write_frame()? Thanks for any and all help!

Sorry for replying to myself, but for future reference, I want to tell the 
solution to my problem, in case someone else stumbles over this. I have to 
say that there is disappointingly little help from actual FFmpeg developers 
on this list. I would expect at least questions for more information, if a 
problem cannot be understood at first.

Anyway, apparently, it is "required" to open the 
AVFormatContext->AVStream->AVCodecContext for every stream. I am doing this 
before calling av_write_header(), as in the output_example.c.

Before you think this should have been obvious, the problem here is that I 
am actually writing two separate plugins. One is wrapping libavformat, and 
it is used only for muxing media files. I realize that I have to put 
sufficient information into the AVFormatContext and the AVStreams I 
allocate, including the codec tag. However, the actual encoding happens in 
a different plugin, which is wrapping just libavcodec. The packet data is 
being passed down to my libavformat plugin, with proper PTS. But the point 
is that the chunk data could be coming from a completely different encoder 
plugin, which has no connection to FFmpeg at all. The AVCodecContext 
instances, which I am now creating in my muxer plugin are not used for 
anything. I just avcodec_open() them before calling av_write_header() and 
close them after calling av_write_trailer(). And then my files have the 
current duration and time base.

Is this behavior intentional? If not, maybe someone could point me at some 
code that could be improved, so that opening the codec contexts is not 
required anymore when just using the muxer functionality.

Best regards,
-Stephan
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to