[Libav-user] Example for recompressing a video?

jettoblack jettoblack at gmail.com
Fri Jun 1 01:37:13 CEST 2012


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.


More information about the Libav-user mailing list