0

我正在尝试将mp4视频文件编码为flv视频。这是我正在做的事情:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

#define STREAM_FRAME_RATE 30 /* 30 images/s */
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
/**************************************************************/
/* Add an output stream. */
static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
        enum AVCodecID codec_id) {
    AVCodecContext *c;
    AVStream *st;
    /* find the encoder */
    *codec = avcodec_find_encoder(codec_id);
    if (!(*codec)) {
        fprintf(stderr, "Could not find encoder for '%s'\n",
                avcodec_get_name(codec_id));
        exit(1);
    }
    st = avformat_new_stream(oc, *codec);
    if (!st) {
        fprintf(stderr, "Could not allocate stream\n");
        exit(1);
    }
    st->id = oc->nb_streams - 1;
    c = st->codec;
    switch ((*codec)->type) {
    case AVMEDIA_TYPE_VIDEO:
        //avcodec_get_context_defaults3(c, *codec);
        c->codec_id = codec_id;
        c->bit_rate = 150 * 1000; //2314000;;
        //c->rc_max_rate = 150*1000;
        //c->rc_buffer_size = 150*1000;
        /* Resolution must be a multiple of two. */
        c->width = 1280;
        c->height = 720;
        /* timebase: This is the fundamental unit of time (in seconds) in terms
         * of which frame timestamps are represented. For fixed-fps content,
         * timebase should be 1/framerate and timestamp increments should be
         * identical to 1. */
        c->time_base.den = STREAM_FRAME_RATE;
        c->time_base.num = 1;
        c->gop_size = 12; /* emit one intra frame every twelve frames at most */
        c->pix_fmt = STREAM_PIX_FMT;
        if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
            /* just for testing, we also add B frames */
            c->max_b_frames = 2;
        }
        if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
            /* Needed to avoid using macroblocks in which some coeffs overflow.
             * This does not happen with normal video, it just happens here as
             * the motion of the chroma plane does not match the luma plane. */
            c->mb_decision = 2;
        }
        break;
    default:
        break;
    }
    /* Some formats want stream headers to be separate. */
    if (oc->oformat->flags & AVFMT_GLOBALHEADER)
        c->flags |= CODEC_FLAG_GLOBAL_HEADER;
    return st;
}
/**************************************************************/
/* video output */
static AVFrame *frame;
static AVPicture src_picture, dst_picture;
static int frame_count;
static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) {
    int ret;
    AVCodecContext *c = st->codec;
    /* open the codec */
    ret = avcodec_open2(c, codec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
        exit(1);
    }
    /* allocate and init a re-usable frame */
    frame = avcodec_alloc_frame();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    /* Allocate the encoded raw picture. */
    ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret));
        exit(1);
    }
    /* If the output format is not YUV420P, then a temporary YUV420P
     * picture is needed too. It is then converted to the required
     * output format. */
    if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
        ret = avpicture_alloc(&src_picture, AV_PIX_FMT_YUV420P, c->width,
                c->height);
        if (ret < 0) {
            fprintf(stderr, "Could not allocate temporary picture: %s\n",
                    av_err2str(ret));
            exit(1);
        }
    }
    /* copy data and linesize picture pointers to frame */
    *((AVPicture *) frame) = dst_picture;
}
static void close_video(AVFormatContext *oc, AVStream *st) {
    avcodec_close(st->codec);
    av_free(src_picture.data[0]);
    av_free(dst_picture.data[0]);
    av_free(frame);
}

int main(int argc, char *argv[]) {
    AVFormatContext *pFormatCtx = NULL;
    int i, videoStream;
    AVCodecContext *pCodecCtx = NULL;
    AVCodec *pCodec;
    AVFrame *pFrame;
    AVPacket packet;
    int frameFinished;

    const char *filename;
    AVOutputFormat *fmt;
    AVFormatContext *oc;
    AVStream *video_st;
    AVCodec *video_codec;
    int ret;

    // Register all formats, codecs and network
    av_register_all();
    avcodec_register_all();
    avformat_network_init();

    // Open video file
    if (avformat_open_input(&pFormatCtx, "input_file.mp4", NULL, NULL) != 0)
        return -1; // Couldn't open file

    // Retrieve stream information
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
        return -1; // Couldn't find stream information

    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, "input_file.mp4", 0);

    // Find the first video stream
    videoStream = -1;
    for (i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->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
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;

    // Find the decoder for the video stream
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL) {
        fprintf(stderr, "Unsupported codec!\n");
        return -1; // Codec not found
    }
    // Open codec
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        return -1; // Could not open codec

    // Allocate video frame
    pFrame = avcodec_alloc_frame();

    // setup mux
    filename = "output_file.flv";
    fmt = av_guess_format("flv", filename, NULL);
    if (fmt == NULL) {
        printf("Could not guess format.\n");
        return -1;
    }
    // allocate the output media context
    oc = avformat_alloc_context();
    if (oc == NULL) {
        printf("could not allocate context.\n");
        return -1;
    }
    oc->oformat = fmt;

    // Add the video streams using the default format codecs
    // and initialize the codecs.
    video_st = NULL;
    if (fmt->video_codec != AV_CODEC_ID_NONE) {
        video_st = add_stream(oc, &video_codec, fmt->video_codec);
    }
    // Now that all the parameters are set, we can open the
    // video codec and allocate the necessary encode buffers.
    if (video_st)
        open_video(oc, video_codec, video_st);

    /* open the output file, if needed */
    if (!(fmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
        if (ret < 0) {
            fprintf(stderr, "Could not open '%s': %s\n", filename,
                    av_err2str(ret));
            return 1;
        }
    }

    // dump output format
    av_dump_format(oc, 0, filename, 1);

    // Write the stream header, if any.
    ret = avformat_write_header(oc, NULL);
    if (ret < 0) {
        fprintf(stderr, "Error occurred when opening output file: %s\n",
                av_err2str(ret));
        return 1;
    }

    // Read frames, decode, and re-encode
    while (av_read_frame(pFormatCtx, &packet) >= 0) {
        // Is this a packet from the video stream?
        if (packet.stream_index == videoStream) {
            // Decode video frame
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

            // Did we get a video frame?
            if (frameFinished) {

                AVFrame* newFrame = avcodec_alloc_frame(); // Initialize a new frame
                int size = avpicture_get_size(video_st->codec->pix_fmt,
                        video_st->codec->width, video_st->codec->height);
                uint8_t* picture_buf = av_malloc(size);

                avpicture_fill((AVPicture *) newFrame, picture_buf,
                        video_st->codec->pix_fmt, video_st->codec->width,
                        video_st->codec->height);

                // Copy only the frame content without any other disturbing
                av_picture_copy((AVPicture*) newFrame, (AVPicture*) pFrame,
                        video_st->codec->pix_fmt, video_st->codec->width,
                        video_st->codec->height);

                // encode the image
                AVPacket pkt;
                int got_output;
                av_init_packet(&pkt);
                pkt.data = NULL; // packet data will be allocated by the encoder
                pkt.size = 0;

                /* Setting newFrame->pts this way produces the error 'non-strictly-monotonic PTS' */
                //if(newFrame->pts != AV_NOPTS_VALUE)
                //newFrame->pts = av_rescale_q(newFrame->pts, video_st->time_base, video_st->codec->time_base);

                // Setting newFrame->pts this does not produce 'non-strictly-monotonic PTS'
                newFrame->pts = frame_count;

                ret = avcodec_encode_video2(video_st->codec, &pkt, newFrame, &got_output);
                if (ret < 0) {
                    fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
                    exit(1);
                }

                if (got_output) {
                    if (video_st->codec->coded_frame->key_frame)
                    pkt.flags |= AV_PKT_FLAG_KEY;
                    pkt.stream_index = video_st->index;

                    if (pkt.pts != AV_NOPTS_VALUE)
                        pkt.pts = av_rescale_q(pkt.pts,
                                video_st->codec->time_base,
                                video_st->time_base);
                    if (pkt.dts != AV_NOPTS_VALUE)
                        pkt.dts = av_rescale_q(pkt.dts,
                                video_st->codec->time_base,
                                video_st->time_base);

                    // Write the compressed frame to the media file.
                    ret = av_interleaved_write_frame(oc, &pkt);
                } else {
                    ret = 0;
                }
                if (ret != 0) {
                    fprintf(stderr, "Error while writing video frame: %s\n",
                            av_err2str(ret));
                    exit(1);
                }

                fprintf(stderr, "encoded frame #%d\n", frame_count);
                frame_count++;
                av_free(picture_buf);
                av_free_packet(&pkt);
            }
        }

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
    }

    /* Write the trailer, if any. The trailer must be written before you
     * close the CodecContexts open when you wrote the header; otherwise
     * av_write_trailer() may try to use memory that was freed on
     * av_codec_close(). */
    av_write_trailer(oc);

    /* Close video encoder (codec). */
    if (video_st)
        close_video(oc, video_st);
    // Free the streams.
    for (i = 0; i < oc->nb_streams; i++) {
        av_freep(&oc->streams[i]->codec);
        av_freep(&oc->streams[i]);
    }
    if (!(fmt->flags & AVFMT_NOFILE))
        /* Close the output file. */
        avio_close(oc->pb);
    /* free the stream */
    av_free(oc);

    // Free the YUV frame holding decoded frame
    av_free(pFrame);

    // Close the decoder (codec)
    avcodec_close(pCodecCtx);

    // Close the input video file
    avformat_close_input(&pFormatCtx);

    return 0;
}

如果我通过更改将输出格式更改为mp4、mov 或 f4v

// setup mux (FLV OUTPUT)
filename = "output_file.flv";
fmt = av_guess_format("flv", filename, NULL);
if (fmt == NULL) {
    printf("Could not guess format.\n");
    return -1;
}

// setup mux (MP4 OUTPUT)
filename = "output_file.mp4";
fmt = av_guess_format("mp4", filename, NULL);
if (fmt == NULL) {
    printf("Could not guess format.\n");
    return -1;
}

然后尊重比特率。这是使用mp4输出运行的输出

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input_file.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
    creation_time   : 2010-02-09 19:11:10
  Duration: 00:04:31.80, start: 0.000000, bitrate: 2314 kb/s
    Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s
    Metadata:
      creation_time   : 2010-02-09 19:11:10
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
    Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 2186 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc
    Metadata:
      creation_time   : 2010-02-09 19:11:10
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
[libx264 @ 02268b80] using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2 AVX
[libx264 @ 02268b80] profile High, level 3.1
[libx264 @ 02268b80] 264 - core 129 r2230 1cffe9f - H.264/MPEG-4 AVC codec - Copyleft 2003-2012 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deb
lock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chro
ma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1
 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=12 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=12 rc=abr mbtree=1 bitrate=150 ratetol=1.0 qco
mp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'output_file.mp4':
    Stream #0:0: Video: h264, yuv420p, 1280x720, q=-1--1, 150 kb/s, 90k tbn, 30 tbc
encoded frame #0
encoded frame #1
encoded frame #2
encoded frame #3
.
.
.
encoded frame #8142
encoded frame #8143
encoded frame #8144
encoded frame #8145
[libx264 @ 02174240] frame I:771   Avg QP:47.71  size:  2739
[libx264 @ 02174240] frame P:5083  Avg QP:50.05  size:   833
[libx264 @ 02174240] frame B:2264  Avg QP:48.16  size:    91
[libx264 @ 02174240] consecutive B-frames: 59.6%  6.4%  9.0% 24.9%
[libx264 @ 02174240] mb I  I16..4: 34.0% 65.8%  0.2%
[libx264 @ 02174240] mb P  I16..4:  6.8%  3.0%  0.0%  P16..4:  8.5%  0.4%  1.7%  0.0%  0.0%    skip:79.6%
[libx264 @ 02174240] mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  1.8%  0.0%  0.0%  direct: 0.0%  skip:98.2%  L0:23.6% L1:76.4% BI: 0.0%
[libx264 @ 02174240] final ratefactor: 57.62
[libx264 @ 02174240] 8x8 transform intra:52.1% inter:98.5%
[libx264 @ 02174240] coded y,uvDC,uvAC intra: 3.1% 14.0% 0.2% inter: 0.1% 0.4% 0.0%
[libx264 @ 02174240] i16 v,h,dc,p: 69% 23%  4%  4%
[libx264 @ 02174240] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23%  6% 68%  1%  1%  1%  1%  0%  0%
[libx264 @ 02174240] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 41% 18% 18%  4%  4%  5%  3%  3%  3%
[libx264 @ 02174240] i8c dc,h,v,p: 98%  1%  1%  0%
[libx264 @ 02174240] Weighted P-Frames: Y:2.1% UV:1.2%
[libx264 @ 02174240] ref P L0: 72.4%  0.8% 19.1%  7.6%  0.1%
[libx264 @ 02174240] ref B L0: 89.8%  9.1%  1.2%
[libx264 @ 02174240] ref B L1: 96.2%  3.8%
[libx264 @ 02174240] kb/s:193.62

output_file.mp4的最终文件大小约为6.5MB,使用 ffplay,我注意到比特率得到了尊重。当然,质量本身就显示出来了。

这是使用flv输出运行的输出:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input_file.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
    creation_time   : 2010-02-09 19:11:10
  Duration: 00:04:31.80, start: 0.000000, bitrate: 2314 kb/s
    Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s
    Metadata:
      creation_time   : 2010-02-09 19:11:10
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
    Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 2186 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc
    Metadata:
      creation_time   : 2010-02-09 19:11:10
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
Output #0, flv, to 'output_file.flv':
    Stream #0:0: Video: flv1, yuv420p, 1280x720, q=2-31, 150 kb/s, 90k tbn, 30 tbc
encoded frame #0
encoded frame #1
encoded frame #2
encoded frame #3
.
.
.
encoded frame #8142
encoded frame #8143
encoded frame #8144
encoded frame #8145

我注意到只要容器是 mp4、mov、f4v 或类似的东西,比特率就会受到尊重。如果我尝试使用 flv、wmv 或其他不同的容器,则比特率不会受到尊重。此外,为 wmv 自动设置的比特率与 flv 不同。我不确定我做错了什么。我怀疑它与pts有关,但是,我找不到解决方案:(。

4

3 回答 3

1

您将视频比特率设置为每秒 150 kbits。它对于 720p 分辨率的视频来说太小了。

您正在使用不同的视频编码器:h264 用于 mp4,Sorenson (flv1) 用于 flv。在这样的比特率下,它们可以以不同的方式工作也就不足为奇了。

于 2013-01-24T09:02:51.410 回答
1

H.264具有非常好的压缩算法并且可以实现非常低的比特率,但对于其他较旧的编解码器(如flv1. 它不是导致这种差异的容器。它的视频编解码器,mp4在 ffmpegh.264默认使用和 flv 使用flv1(h.263)。容器也flv支持h.264。如果它只是您感兴趣的容器,请将 vcodec 设置为h.264or libx264,您将获得与mp4.

于 2013-01-24T09:33:51.773 回答
0

感谢您的帮助!我忘记了我正在将默认格式编解码器传递给add_stream函数。因此,我使用了 flv 的默认值(正如您提到的,对于 mp4 是 flv1 和 h.264,对于 wmv 是 msmpeg4v3)。上面代码中的错误来源是以下行:

// Add the video streams using the default format codecs
// and initialize the codecs.
video_st = NULL;
if (fmt->video_codec != AV_CODEC_ID_NONE) {
    video_st = add_stream(oc, &video_codec, fmt->video_codec);
}

将其更改为:

// Add the video stream using the h.264
// codec and initialize the codec.
video_st = NULL;
video_st = add_stream(oc, &video_codec, AV_CODEC_ID_H264);

解决了这个问题。这是固定的源代码/输出:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

#define STREAM_FRAME_RATE 30 /* 30 frames/s */
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
/**************************************************************/
/* video output */
static AVFrame *frame;
static AVPicture src_picture, dst_picture;
static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) {
    int ret;
    AVCodecContext *c = st->codec;
    /* open the codec */
    ret = avcodec_open2(c, codec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
        exit(1);
    }
    /* allocate and init a re-usable frame */
    frame = avcodec_alloc_frame();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    /* Allocate the encoded raw picture. */
    ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret));
        exit(1);
    }
    /* If the output format is not YUV420P, then a temporary YUV420P
     * picture is needed too. It is then converted to the required
     * output format. */
    if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
        ret = avpicture_alloc(&src_picture, AV_PIX_FMT_YUV420P, c->width, c->height);
        if (ret < 0) {
            fprintf(stderr, "Could not allocate temporary picture: %s\n", av_err2str(ret));
            exit(1);
        }
    }
    /* copy data and linesize picture pointers to frame */
    *((AVPicture *) frame) = dst_picture;
}
static void close_video(AVFormatContext *oc, AVStream *st) {
    avcodec_close(st->codec);
    av_free(src_picture.data[0]);
    av_free(dst_picture.data[0]);
    av_free(frame);
}
/**************************************************************/
/* Add an output stream. */
static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id) {
    AVCodecContext *c;
    AVStream *st;
    /* find the encoder */
    *codec = avcodec_find_encoder(codec_id);
    if (!(*codec)) {
        fprintf(stderr, "Could not find encoder for '%s'\n", avcodec_get_name(codec_id));
        exit(1);
    }
    st = avformat_new_stream(oc, *codec);
    if (!st) {
        fprintf(stderr, "Could not allocate stream\n");
        exit(1);
    }
    st->id = oc->nb_streams - 1;
    c = st->codec;
    switch ((*codec)->type) {
    case AVMEDIA_TYPE_VIDEO:
        avcodec_get_context_defaults3(c, *codec);
        c->codec_id = codec_id;
        c->bit_rate = 150 * 1000;
        /* Resolution must be a multiple of two. */
        c->width = 1280;
        c->height = 720;
        /* timebase: This is the fundamental unit of time (in seconds) in terms
         * of which frame timestamps are represented. For fixed-fps content,
         * timebase should be 1/framerate and timestamp increments should be
         * identical to 1. */
        c->time_base.den = STREAM_FRAME_RATE;
        c->time_base.num = 1;
        c->gop_size = 12; /* emit one intra frame every twelve frames at most */
        c->pix_fmt = STREAM_PIX_FMT;
        if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
            /* just for testing, we also add B frames */
            c->max_b_frames = 2;
        }
        if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
            /* Needed to avoid using macroblocks in which some coeffs overflow.
             * This does not happen with normal video, it just happens here as
             * the motion of the chroma plane does not match the luma plane. */
            c->mb_decision = 2;
        }
        break;
    default:
        break;
    }
    /* Some formats want stream headers to be separate. */
    if (oc->oformat->flags & AVFMT_GLOBALHEADER)
        c->flags |= CODEC_FLAG_GLOBAL_HEADER;
    return st;
}

int main(int argc, char *argv[]) {
    // Decoder local variable declaration
    AVFormatContext *pFormatCtx = NULL;
    int i, videoStream;
    AVCodecContext *pCodecCtx = NULL;
    AVCodec *pCodec;
    AVFrame *pFrame;
    AVPacket packet;
    int frameFinished;

    // Encoder local variable declaration
    const char *filename;
    AVOutputFormat *fmt;
    AVFormatContext *oc;
    AVStream *video_st;
    AVCodec *video_codec;
    int ret, frame_count;

    // Register all formats and codecs
    av_register_all();
    avcodec_register_all();

    // Open video file
    if (avformat_open_input(&pFormatCtx, "input_file.mp4", NULL, NULL) != 0)
        return -1; // Couldn't open file

    // Retrieve stream information
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
        return -1; // Couldn't find stream information

    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, "input_file.mp4", 0);

    // Find the first video stream
    videoStream = -1;
    for (i = 0; i < pFormatCtx->nb_streams; i++)
        if (pFormatCtx->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
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;

    // Find the decoder for the video stream
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL) {
        fprintf(stderr, "Unsupported codec!\n");
        return -1; // Codec not found
    }
    // Open codec (decoder)
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        return -1; // Could not open codec

    // Allocate video frame
    pFrame = avcodec_alloc_frame();

    // setup mux
    filename = "output_file.flv";
    fmt = av_guess_format("flv", filename, NULL);
    if (fmt == NULL) {
        printf("Could not guess format.\n");
        return -1;
    }
    // allocate the output media context
    oc = avformat_alloc_context();
    if (oc == NULL) {
        printf("could not allocate context.\n");
        return -1;
    }

    // Set out format context to the format ffmpeg guessed
    oc->oformat = fmt;

    // Add the video stream using the h.264
    // codec and initialize the codec.
    video_st = NULL;
    video_st = add_stream(oc, &video_codec, AV_CODEC_ID_H264);

    // Now that all the parameters are set, we can open the
    // video codec and allocate the necessary encode buffers.
    if (video_st)
        open_video(oc, video_codec, video_st);

    /* open the output file, if needed */
    if (!(fmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
        if (ret < 0) {
            fprintf(stderr, "Could not open '%s': %s\n", filename, av_err2str(ret));
            return 1;
        }
    }

    // dump output format
    av_dump_format(oc, 0, filename, 1);

    // Write the stream header, if any.
    ret = avformat_write_header(oc, NULL);
    if (ret < 0) {
        fprintf(stderr, "Error occurred when opening output file: %s\n", av_err2str(ret));
        return 1;
    }

    // Read frames, decode, and re-encode
    frame_count = 1;
    while (av_read_frame(pFormatCtx, &packet) >= 0) {
        // Is this a packet from the video stream?
        if (packet.stream_index == videoStream) {
            // Decode video frame
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

            // Did we get a video frame?
            if (frameFinished) {

                // Initialize a new frame
                AVFrame* newFrame = avcodec_alloc_frame();

                int size = avpicture_get_size(video_st->codec->pix_fmt, video_st->codec->width, video_st->codec->height);
                uint8_t* picture_buf = av_malloc(size);

                avpicture_fill((AVPicture *) newFrame, picture_buf, video_st->codec->pix_fmt, video_st->codec->width, video_st->codec->height);

                // Copy only the frame content without additional fields
                av_picture_copy((AVPicture*) newFrame, (AVPicture*) pFrame, video_st->codec->pix_fmt, video_st->codec->width, video_st->codec->height);

                // encode the image
                AVPacket pkt;
                int got_output;
                av_init_packet(&pkt);
                pkt.data = NULL; // packet data will be allocated by the encoder
                pkt.size = 0;

                // Set the frame's pts (this prevents the warning notice 'non-strictly-monotonic PTS')
                newFrame->pts = frame_count;

                ret = avcodec_encode_video2(video_st->codec, &pkt, newFrame, &got_output);
                if (ret < 0) {
                    fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
                    exit(1);
                }

                if (got_output) {
                    if (video_st->codec->coded_frame->key_frame)
                        pkt.flags |= AV_PKT_FLAG_KEY;
                    pkt.stream_index = video_st->index;

                    if (pkt.pts != AV_NOPTS_VALUE)
                        pkt.pts = av_rescale_q(pkt.pts, video_st->codec->time_base, video_st->time_base);
                    if (pkt.dts != AV_NOPTS_VALUE)
                        pkt.dts = av_rescale_q(pkt.dts, video_st->codec->time_base, video_st->time_base);

                    // Write the compressed frame to the media file.
                    ret = av_interleaved_write_frame(oc, &pkt);
                } else {
                    ret = 0;
                }
                if (ret != 0) {
                    fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
                    exit(1);
                }

                fprintf(stderr, "encoded frame #%d\n", frame_count);
                frame_count++;

                // Free the YUV picture frame we copied from the
                // decoder to eliminate the additional fields
                // and other packets/frames used
                av_free(picture_buf);
                av_free_packet(&pkt);
                av_free(newFrame);
            }
        }

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
    }

    /* Write the trailer, if any. The trailer must be written before you
     * close the CodecContexts open when you wrote the header; otherwise
     * av_write_trailer() may try to use memory that was freed on
     * av_codec_close(). */
    av_write_trailer(oc);

    /* Close the video codec (encoder) */
    if (video_st)
        close_video(oc, video_st);
    // Free the output streams.
    for (i = 0; i < oc->nb_streams; i++) {
        av_freep(&oc->streams[i]->codec);
        av_freep(&oc->streams[i]);
    }
    if (!(fmt->flags & AVFMT_NOFILE))
        /* Close the output file. */
        avio_close(oc->pb);
    /* free the output format context */
    av_free(oc);

    // Free the YUV frame populated by the decoder
    av_free(pFrame);

    // Close the video codec (decoder)
    avcodec_close(pCodecCtx);

    // Close the input video file
    avformat_close_input(&pFormatCtx);

    return 0;
}

这是输出:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input_file.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
    creation_time   : 2010-02-09 19:11:10
  Duration: 00:04:31.80, start: 0.000000, bitrate: 2314 kb/s
    Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s
    Metadata:
      creation_time   : 2010-02-09 19:11:10
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
    Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 2186 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc
    Metadata:
      creation_time   : 2010-02-09 19:11:10
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
video codec id = 28 | name = FLV (Flash Video)
[libx264 @ 021891c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2 AVX
[libx264 @ 021891c0] profile High, level 3.1
[libx264 @ 021891c0] 264 - core 129 r2230 1cffe9f - H.264/MPEG-4 AVC codec - Copyleft 2003-2012 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deb
lock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chro
ma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1
 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=12 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=12 rc=abr mbtree=1 bitrate=150 ratetol=1.0 qco
mp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, flv, to 'output_file.flv':
    Stream #0:0: Video: h264, yuv420p, 1280x720, q=-1--1, 150 kb/s, 90k tbn, 30 tbc
encoded frame #1
encoded frame #2
encoded frame #3
encoded frame #4
.
.
.
encoded frame #8143
encoded frame #8144
encoded frame #8145
encoded frame #8146
[libx264 @ 02241ae0] frame I:771   Avg QP:47.71  size:  2739
[libx264 @ 02241ae0] frame P:5083  Avg QP:50.05  size:   833
[libx264 @ 02241ae0] frame B:2264  Avg QP:48.16  size:    91
[libx264 @ 02241ae0] consecutive B-frames: 59.6%  6.4%  9.0% 24.9%
[libx264 @ 02241ae0] mb I  I16..4: 34.0% 65.8%  0.2%
[libx264 @ 02241ae0] mb P  I16..4:  6.8%  3.0%  0.0%  P16..4:  8.5%  0.4%  1.7%  0.0%  0.0%    skip:79.6%
[libx264 @ 02241ae0] mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  1.8%  0.0%  0.0%  direct: 0.0%  skip:98.2%  L0:23.6% L1:76.4% BI: 0.0%
[libx264 @ 02241ae0] final ratefactor: 57.62
[libx264 @ 02241ae0] 8x8 transform intra:52.1% inter:98.5%
[libx264 @ 02241ae0] coded y,uvDC,uvAC intra: 3.1% 14.0% 0.2% inter: 0.1% 0.4% 0.0%
[libx264 @ 02241ae0] i16 v,h,dc,p: 69% 23%  4%  4%
[libx264 @ 02241ae0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23%  6% 68%  1%  1%  1%  1%  0%  0%
[libx264 @ 02241ae0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 41% 18% 18%  4%  4%  5%  3%  3%  3%
[libx264 @ 02241ae0] i8c dc,h,v,p: 98%  1%  1%  0%
[libx264 @ 02241ae0] Weighted P-Frames: Y:2.1% UV:1.2%
[libx264 @ 02241ae0] ref P L0: 72.4%  0.8% 19.1%  7.6%  0.1%
[libx264 @ 02241ae0] ref B L0: 89.8%  9.1%  1.2%
[libx264 @ 02241ae0] ref B L1: 96.2%  3.8%
[libx264 @ 02241ae0] kb/s:193.62

感谢您的帮助!

于 2013-01-24T13:58:56.920 回答