[Libav-user] Getting started with libav, some problems and questions.

Vadim Gusev ubuntolog at gmail.com
Sun May 8 19:30:30 CEST 2011


Hi everyone in this list. I'm trying to write a simple video split/merge
program, that will be part of daemon.
I've looked trough api-example.c and output-example.c and written simple
program that almost works.
For now i'm just trying to re-encode input file, actual encoding works
almost fine but muxing causes problems:

1) when trying to seek output file with mplayer i get this messages: [mpeg4
@ 0x7fcd7bf12b80]warning: first frame is no keyframe
and playback is broken till next keyframe, like it happens when keyframe is
missing/broken.
But i've checked CODEC_ID_MPEG4 codec case: kayfarmes are exactly
first+n*gop_size (30 in my case)
CODEC_ID_H264 is more complex, will describe below

2) both CODEC_ID_H264 and CODEC_ID_MPEG4 give much lower bitrate, than i've
set.
Desired bitrate: 10Mbps
CODEC_ID_H264: 723kbps
CODEC_ID_MPEG4: 1142kbps

3) when trying CODEC_ID_H264 i get error for each frame: [libx264 @
0xf3e160] non-strictly-monotonic PTS
and additionally first 50 frames are 0-sized, plus post-encode statistics
are completely broken.
Keyframes for gop size = 30, 200 frames input are this: 49, 100, 143. Looks
strange for me.

I think i've got lack of understanding how muxing should work, especially
this PTS magic, so it would be nice if someone
would point what am i doing wrong or not doing, but should.

Thanks in advance. Here is source code of my program:

#include <libavcodec/avcodec.h>
> #include <libavformat/avformat.h>
> #include <libswscale/swscale.h>
>
>     AVFormatContext        *in_ctx;
>     AVFormatContext        *out_ctx;
>     AVCodecContext         *in_codec_ctx;
>     AVCodecContext         *out_codec_ctx;
>     AVCodec                *in_codec;
>     AVCodec                *out_codec;
>     AVStream               *video_st;
>     int                    videoStream = -1;
>
>
> int open_input_file(char *filename) {
>
>    // Open video file
>     if(av_open_input_file(&in_ctx, filename, NULL, 0, NULL) != 0)
>         return -1; // Couldn't open file
>
>     // Retrieve stream information
>     if(av_find_stream_info(in_ctx) < 0)
>         return -1; // Couldn't find stream information
>
>     // Find the first video stream
>     int i;
>     for(i = 0; i < in_ctx->nb_streams; i++)
>         if(in_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
>             videoStream = i;
>             break;
>         }
>     if(videoStream == -1)
>         return -1; // Didn't find a video stream
>
>     // Get a pointer to the codec context for the video stream
>     in_codec_ctx = in_ctx->streams[videoStream]->codec;
>
>     // Find the decoder for the video stream
>     in_codec = avcodec_find_decoder(in_codec_ctx->codec_id);
>     if(in_codec == NULL) {
>         fprintf(stderr, "Unsupported input codec!\n");
>         return -1; // Codec not found
>     }
>     // Open codec
>     if(avcodec_open(in_codec_ctx, in_codec) < 0)
>         return -1; // Could not open codec
>
>     return 0;
> }
>
> int create_out_file(char *filename) {
>     // Allocate output format context
>     out_ctx = avformat_alloc_context();
>     out_ctx->oformat = av_guess_format(NULL, filename, NULL);
>     if (out_ctx->oformat == NULL)
>     {
>         fprintf(stderr, "Could not guess output format\n");
>         exit(1);
>     }
>
>     snprintf(out_ctx->filename, sizeof(out_ctx->filename), "%s", filename);
>
>     video_st = av_new_stream(out_ctx, 0);
>     if (!video_st) {
>         fprintf(stderr, "Could not alloc stream\n");
>         exit(1);
>     }
>
>     out_codec_ctx = video_st->codec;
>     out_codec_ctx->codec_id = CODEC_ID_H264;
>     out_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
>     out_codec_ctx->bit_rate = 10000000;
>     //out_codec_ctx->crf = 10;
>     out_codec_ctx->width = in_codec_ctx->width;
>     out_codec_ctx->height = in_codec_ctx->height;
>     out_codec_ctx->time_base.den = in_codec_ctx->time_base.den;
>     out_codec_ctx->time_base.num = in_codec_ctx->time_base.num;
>     out_codec_ctx->gop_size = 30;
>     out_codec_ctx->pix_fmt = PIX_FMT_YUV420P;
>     out_codec_ctx->thread_count = 4;
>     out_codec_ctx->rc_lookahead = 100;
>
>     if(out_ctx->oformat->flags & AVFMT_GLOBALHEADER)
>         out_codec_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
>
>     out_codec_ctx->flags2 |= CODEC_FLAG2_SSIM;
>     out_codec_ctx->flags |= CODEC_FLAG_PSNR;
>
>
>     // Find the encoder for the video stream
>     out_codec = avcodec_find_encoder(out_codec_ctx->codec_id);
>     if(out_codec == NULL) {
>         fprintf(stderr, "Unsupported output codec!\n");
>         return -1; // Codec not found
>     }
>     // Open codec
>     if(avcodec_open(out_codec_ctx, out_codec) < 0)
>         return -1; // Could not open codec
>
>     avio_open(&out_ctx->pb, filename, AVIO_FLAG_WRITE);
>     av_write_header(out_ctx);
>
>     return 0;
> }
>
> int main(int argc, char **argv) {
>
>     AVFrame                 *picture;
>     int                     picture_size;
>     AVFrame                 *tmp_picture;
>     int                     out_size;
>     int                     frame_count = 0;
>     int                     frame_finished;
>     AVPacket                packet;
>     uint8_t                 *buffer;
>     struct SwsContext       *img_convert_ctx;
>     int                     retval;
>
>     av_register_all();
>
>     if (open_input_file(argv[1]))
>         exit(1);
>     if (create_out_file(argv[2]))
>         exit(1);
>
>     av_dump_format(in_ctx, 0, argv[1], 0);
>     av_dump_format(out_ctx, 0, argv[2], 1);
>
>     //Allocate frame for decoding
>     tmp_picture = avcodec_alloc_frame();
>
>     //Allocate frame fro encoding
>     picture = avcodec_alloc_frame();
>     picture_size = avpicture_get_size(out_codec_ctx->pix_fmt,
> out_codec_ctx->width, out_codec_ctx->height);
>     buffer=(uint8_t *)av_malloc(picture_size * sizeof(uint8_t));
>     avpicture_fill((AVPicture *)picture, buffer, out_codec_ctx->pix_fmt,
> out_codec_ctx->width, out_codec_ctx->height);
>
>     //Crate scaler context
>     img_convert_ctx = sws_getContext(in_codec_ctx->width,
> in_codec_ctx->height, in_codec_ctx->pix_fmt,
>                                     out_codec_ctx->width,
> out_codec_ctx->height, out_codec_ctx->pix_fmt,
>                                     SWS_BICUBIC, NULL, NULL, NULL);
>     if (img_convert_ctx == NULL) {
>         fprintf(stderr, "Cannot initialize the conversion context\n");
>         exit(1);
>     }
>
>     av_init_packet(&packet);
>
>     while (av_read_frame(in_ctx, &packet) >= 0) {
>         if(packet.stream_index == videoStream) {
>             frame_count++;
>             //printf("Encoding frame %d\n", frame_count);
>             //Decode
>             retval = avcodec_decode_video2(in_codec_ctx, tmp_picture,
> &frame_finished, &packet);
>             if (retval < 0)
>                 fprintf(stderr, "Error decoding frame\t%d\n", frame_count);
>
>             //Scale
>             retval= sws_scale(img_convert_ctx, tmp_picture->data,
> tmp_picture->linesize,
>                       0, out_codec_ctx->height, picture->data,
> picture->linesize);
>             if (retval < 1)
>                 fprintf(stderr, "Error scaling frame\t%d\n", frame_count);
>
>             //Encode
>             out_size = avcodec_encode_video(out_codec_ctx, buffer,
> picture_size, picture);
>             if (out_size <= 0) {
>                 fprintf(stderr, "Error encoding frame\t%d\n", frame_count);
>             } else {
>             //Write
>                 if (out_codec_ctx->coded_frame->pts != AV_NOPTS_VALUE)
>                     packet.pts =
> av_rescale_q(out_codec_ctx->coded_frame->pts, out_codec_ctx->time_base,
> video_st->time_base);
>                 if (out_codec_ctx->coded_frame->key_frame) {
>                     packet.flags |= AV_PKT_FLAG_KEY;
>                     printf("frame %d is key\n", frame_count);
>                 }
>                 packet.stream_index = video_st->index;
>                 packet.data = buffer;
>                 packet.size = out_size;
>                 av_write_frame(out_ctx, &packet);
>             }
>         }
>     }
>
>     av_write_trailer(out_ctx);
>
>
>     av_free_packet(&packet);
>     av_free(buffer);
>     av_free(picture);
>     av_free(tmp_picture);
>     avcodec_close(in_codec_ctx);
>     avcodec_close(out_codec_ctx);
>     av_close_input_file(in_ctx);
>     avio_close(out_ctx->pb);
>
>     return 0;
> }
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20110508/b2a4f49f/attachment.html>


More information about the Libav-user mailing list