[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