[Libav-user] Example for recompressing a video?
Christian Brümmer
christian.bruemmer at gmx.de
Fri Jun 1 11:57:38 CEST 2012
Am 01.06.2012 01:37, schrieb jettoblack:
> Hello,
> I'd like to use libavformat to recompress a video file, similar to ffmpeg
> standalone but much simpler (fixed codec parameters, etc.). I've figured
> out how to remux (without re-encoding), but I'm not sure on recompressing.
>
> I used the output-example.c as a starting point, but it generates fake
> video/audio data in temporal order. In my case I am demuxing a IPB encoded
> video so the frames are decoded out of order. What is the proper way to
> re-encode these in order? If I simply pass each picture into the encoder in
> the order that they come out of the decoder, I get errors like
> "non-strictly-monotonic PTS" from the encoder.
>
> Here's my loop, I assume I'm overlooking some major points.
>
> while (1) {
> av_init_packet(&pkt);
> r = av_read_frame(in,&pkt);
> if (r) {
> if (r == AVERROR_EOF)
> printf("EOF\n");
> else
> printf("read error %x\n", r);
> break;
> }
> printf("stream %d, pts %"PRId64", dts %"PRId64"\n",
> pkt.stream_index, pkt.pts, pkt.dts);
>
> if (pkt.stream_index == in_vstream->index) {
> picture = avcodec_alloc_frame();
> assert(picture);
> avcodec_decode_video2(in_vcodec, picture,&got_picture,&pkt);
> if (got_picture) {
> printf("got picture: pts %"PRId64"\n", pkt.pts);
>
> // convert picture to dest format
> AVFrame *newpicture = avcodec_alloc_frame();
> avpicture_fill((AVPicture*)newpicture, picbuf,
> out_vcodec->pix_fmt, out_vcodec->width, out_vcodec->height);
> sws_scale(img_convert_ctx, picture->data, picture->linesize,
> 0, in_vcodec->height, newpicture->data, newpicture->linesize);
>
> // write picture
> int got_packet_ptr = 0;
> AVPacket newpkt;
> av_init_packet(&newpkt);
> r = avcodec_encode_video2(out_vcodec,&newpkt, newpicture,
> &got_packet_ptr);
> assert(!r);
> if (got_packet_ptr) {
> printf("got_packet_ptr\n");
> newpkt.stream_index = out_vstream->index;
> newpkt.pts = av_rescale_q(out_vcodec->coded_frame->pts,
> out_vcodec->time_base, out_vstream->time_base);
> printf("write newpkt: stream %d, pts %"PRId64", dts
> %"PRId64"\n", newpkt.stream_index, newpkt.pts, newpkt.dts);
> r = av_interleaved_write_frame(out,&newpkt);
> if (r&& (r != AVERROR(EINVAL))) {
> printf("write error %x\n", r);
> }
> assert(!r);
> }
> av_free_packet(&newpkt);
> av_free(newpicture);
> video_frames++;
>
> }
> av_free(picture);
> }
> else if (pkt.stream_index == in_astream->index) {
> // get audio
> // compress audio
> // write audio
>
> // write frame
> r = av_interleaved_write_frame(out,&pkt);
> if (r&& (r != AVERROR(EINVAL))) {
> printf("write error %x\n", r);
> }
> }
>
> av_free_packet(&pkt);
>
> }
>
> This loop chugs along with a bunch of "non-strictly-monotonic PTS" warnings
> until it gets to the first time the encoder returns got_packet_ptr = true,
> then it segfaults on av_interleaved_write_frame(out,&newpkt);
>
> I'm quite sure I'm doing something wrong, any ideas? :) Are there any other
> better examples out there (other than ffmpeg.c -- too complex) for me to
> start with?
>
> Thanks!
>
>
>
> --
> View this message in context: http://libav-users.943685.n4.nabble.com/Example-for-recompressing-a-video-tp4655098.html
> Sent from the libav-users mailing list archive at Nabble.com.
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
>
Don't nothing about reordering but you can get rid of the
"non-strictly-monotonic PTS" warnings. You have to set the right pts
value (and dts if you want to encode audio too) for you AVFrame
(newpicture).
This is a codec dependent value in case of h264 its some thing like that:
mPicture->pts = (float) mFrameCount *
(1000.0/(float)(mParameters.mFrameRate)) * 90;
So you have to look whats a right pts for your destination video.
More information about the Libav-user
mailing list