Hi everyone in this list. I'm trying to write a simple video split/merge program, that will be part of daemon.<br>I've looked trough api-example.c and output-example.c and written simple program that almost works.<br>
For now i'm just trying to re-encode input file, actual encoding works almost fine but muxing causes problems:<br><br>1) when trying to seek output file with mplayer i get this messages: [mpeg4 @ 0x7fcd7bf12b80]warning: first frame is no keyframe<br>
and playback is broken till next keyframe, like it happens when keyframe is missing/broken.<br>But i've checked CODEC_ID_MPEG4 codec case: kayfarmes are exactly first+n*gop_size (30 in my case)<br>CODEC_ID_H264 is more complex, will describe below<br>
<br>2) both CODEC_ID_H264 and CODEC_ID_MPEG4 give much lower bitrate, than i've set.<br>Desired bitrate: 10Mbps<br>CODEC_ID_H264: 723kbps<br>CODEC_ID_MPEG4: 1142kbps<br><br>3) when trying CODEC_ID_H264 i get error for each frame: [libx264 @ 0xf3e160] non-strictly-monotonic PTS<br>
and additionally first 50 frames are 0-sized, plus post-encode statistics are completely broken.<br>Keyframes for gop size = 30, 200 frames input are this: 49, 100, 143. Looks strange for me.<br><br>I think i've got lack of understanding how muxing should work, especially this PTS magic, so it would be nice if someone<br>
would point what am i doing wrong or not doing, but should.<br><br>Thanks in advance. Here is source code of my program:<br><br><blockquote style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class="gmail_quote">
#include <libavcodec/avcodec.h><br>#include <libavformat/avformat.h><br>#include <libswscale/swscale.h><br><br>    AVFormatContext        *in_ctx;<br>    AVFormatContext        *out_ctx;<br>    AVCodecContext         *in_codec_ctx;<br>
    AVCodecContext         *out_codec_ctx;<br>    AVCodec                *in_codec;<br>    AVCodec                *out_codec;<br>    AVStream               *video_st;<br>    int                    videoStream = -1;<br><br>
<br>int open_input_file(char *filename) {<br><br>   // Open video file<br>    if(av_open_input_file(&in_ctx, filename, NULL, 0, NULL) != 0)<br>        return -1; // Couldn't open file<br><br>    // Retrieve stream information<br>
    if(av_find_stream_info(in_ctx) < 0)<br>        return -1; // Couldn't find stream information<br><br>    // Find the first video stream<br>    int i;<br>    for(i = 0; i < in_ctx->nb_streams; i++)<br>        if(in_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {<br>
            videoStream = i;<br>            break;<br>        }<br>    if(videoStream == -1)<br>        return -1; // Didn't find a video stream<br><br>    // Get a pointer to the codec context for the video stream<br>
    in_codec_ctx = in_ctx->streams[videoStream]->codec;<br><br>    // Find the decoder for the video stream<br>    in_codec = avcodec_find_decoder(in_codec_ctx->codec_id);<br>    if(in_codec == NULL) {<br>        fprintf(stderr, "Unsupported input codec!\n");<br>
        return -1; // Codec not found<br>    }<br>    // Open codec<br>    if(avcodec_open(in_codec_ctx, in_codec) < 0)<br>        return -1; // Could not open codec<br><br>    return 0;<br>}<br><br>int create_out_file(char *filename) {<br>
    // Allocate output format context<br>    out_ctx = avformat_alloc_context();<br>    out_ctx->oformat = av_guess_format(NULL, filename, NULL);<br>    if (out_ctx->oformat == NULL)<br>    {<br>        fprintf(stderr, "Could not guess output format\n");<br>
        exit(1);<br>    }<br><br>    snprintf(out_ctx->filename, sizeof(out_ctx->filename), "%s", filename);<br><br>    video_st = av_new_stream(out_ctx, 0);<br>    if (!video_st) {<br>        fprintf(stderr, "Could not alloc stream\n");<br>
        exit(1);<br>    }<br><br>    out_codec_ctx = video_st->codec;<br>    out_codec_ctx->codec_id = CODEC_ID_H264;<br>    out_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;<br>    out_codec_ctx->bit_rate = 10000000;<br>
    //out_codec_ctx->crf = 10;<br>    out_codec_ctx->width = in_codec_ctx->width;<br>    out_codec_ctx->height = in_codec_ctx->height;<br>    out_codec_ctx->time_base.den = in_codec_ctx->time_base.den;<br>
    out_codec_ctx->time_base.num = in_codec_ctx->time_base.num;<br>    out_codec_ctx->gop_size = 30;<br>    out_codec_ctx->pix_fmt = PIX_FMT_YUV420P;<br>    out_codec_ctx->thread_count = 4;<br>    out_codec_ctx->rc_lookahead = 100;<br>
<br>    if(out_ctx->oformat->flags & AVFMT_GLOBALHEADER)<br>        out_codec_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;<br><br>    out_codec_ctx->flags2 |= CODEC_FLAG2_SSIM;<br>    out_codec_ctx->flags |= CODEC_FLAG_PSNR;<br>
<br><br>    // Find the encoder for the video stream<br>    out_codec = avcodec_find_encoder(out_codec_ctx->codec_id);<br>    if(out_codec == NULL) {<br>        fprintf(stderr, "Unsupported output codec!\n");<br>
        return -1; // Codec not found<br>    }<br>    // Open codec<br>    if(avcodec_open(out_codec_ctx, out_codec) < 0)<br>        return -1; // Could not open codec<br><br>    avio_open(&out_ctx->pb, filename, AVIO_FLAG_WRITE);<br>
    av_write_header(out_ctx);<br><br>    return 0;<br>}<br><br>int main(int argc, char **argv) {<br><br>    AVFrame                 *picture;<br>    int                     picture_size;<br>    AVFrame                 *tmp_picture;<br>
    int                     out_size;<br>    int                     frame_count = 0;<br>    int                     frame_finished;<br>    AVPacket                packet;<br>    uint8_t                 *buffer;<br>    struct SwsContext       *img_convert_ctx;<br>
    int                     retval;<br><br>    av_register_all();<br><br>    if (open_input_file(argv[1]))<br>        exit(1);<br>    if (create_out_file(argv[2]))<br>        exit(1);<br><br>    av_dump_format(in_ctx, 0, argv[1], 0);<br>
    av_dump_format(out_ctx, 0, argv[2], 1);<br><br>    //Allocate frame for decoding<br>    tmp_picture = avcodec_alloc_frame();<br><br>    //Allocate frame fro encoding<br>    picture = avcodec_alloc_frame();<br>    picture_size = avpicture_get_size(out_codec_ctx->pix_fmt, out_codec_ctx->width, out_codec_ctx->height);<br>
    buffer=(uint8_t *)av_malloc(picture_size * sizeof(uint8_t));<br>    avpicture_fill((AVPicture *)picture, buffer, out_codec_ctx->pix_fmt, out_codec_ctx->width, out_codec_ctx->height);<br><br>    //Crate scaler context<br>
    img_convert_ctx = sws_getContext(in_codec_ctx->width, in_codec_ctx->height, in_codec_ctx->pix_fmt,<br>                                    out_codec_ctx->width, out_codec_ctx->height, out_codec_ctx->pix_fmt,<br>
                                    SWS_BICUBIC, NULL, NULL, NULL);<br>    if (img_convert_ctx == NULL) {<br>        fprintf(stderr, "Cannot initialize the conversion context\n");<br>        exit(1);<br>    }<br>
<br>    av_init_packet(&packet);<br><br>    while (av_read_frame(in_ctx, &packet) >= 0) {<br>        if(packet.stream_index == videoStream) {<br>            frame_count++;<br>            //printf("Encoding frame %d\n", frame_count);<br>
            //Decode<br>            retval = avcodec_decode_video2(in_codec_ctx, tmp_picture, &frame_finished, &packet);<br>            if (retval < 0)<br>                fprintf(stderr, "Error decoding frame\t%d\n", frame_count);<br>
<br>            //Scale<br>            retval= sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,<br>                      0, out_codec_ctx->height, picture->data, picture->linesize);<br>            if (retval < 1)<br>
                fprintf(stderr, "Error scaling frame\t%d\n", frame_count);<br><br>            //Encode<br>            out_size = avcodec_encode_video(out_codec_ctx, buffer, picture_size, picture);<br>            if (out_size <= 0) {<br>
                fprintf(stderr, "Error encoding frame\t%d\n", frame_count);<br>            } else {<br>            //Write<br>                if (out_codec_ctx->coded_frame->pts != AV_NOPTS_VALUE)<br>                    packet.pts = av_rescale_q(out_codec_ctx->coded_frame->pts, out_codec_ctx->time_base, video_st->time_base);<br>
                if (out_codec_ctx->coded_frame->key_frame) {<br>                    packet.flags |= AV_PKT_FLAG_KEY;<br>                    printf("frame %d is key\n", frame_count);<br>                }<br>
                packet.stream_index = video_st->index;<br>                packet.data = buffer;<br>                packet.size = out_size;<br>                av_write_frame(out_ctx, &packet);<br>            }<br>        }<br>
    }<br><br>    av_write_trailer(out_ctx);<br><br><br>    av_free_packet(&packet);<br>    av_free(buffer);<br>    av_free(picture);<br>    av_free(tmp_picture);<br>    avcodec_close(in_codec_ctx);<br>    avcodec_close(out_codec_ctx);<br>
    av_close_input_file(in_ctx);<br>    avio_close(out_ctx->pb);<br><br>    return 0;<br>}<br></blockquote>