`
kongweile
  • 浏览: 517454 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

FFMpeg官网源代码中的示例代码(编码和解码示例)(精华)

 
阅读更多

转:http://blog.csdn.net/cosmoslife/article/details/7583275

//FFMpeg学习官网地址:http://www.ffmpeg.org/developer.html

 

/*
 * Copyright (c) 2001 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * @file
 * libavcodec API use example.
 *
 * Note that libavcodec only handles codecs (mpeg, mpeg4, etc...),
 * not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the
 * format handling
 */

#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"

#define INBUF_SIZE 4096
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096

/*
 * Audio encoding example
 */
static void audio_encode_example(const char *filename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int frame_size, i, j, out_size, outbuf_size;
    FILE *f;
    short *samples;
    float t, tincr;
    uint8_t *outbuf;

    printf("Audio encoding\n");

    /* find the MP2 encoder */
    codec = avcodec_find_encoder(CODEC_ID_MP2);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);

    /* put sample parameters */
    c->bit_rate = 64000;
    c->sample_rate = 44100;
    c->channels = 2;
    c->sample_fmt = AV_SAMPLE_FMT_S16;

    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    /* the codec gives us the frame size, in samples */
    frame_size = c->frame_size;
    samples = malloc(frame_size * 2 * c->channels);
    outbuf_size = 10000;
    outbuf = malloc(outbuf_size);

    f = fopen(filename, "wb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    /* encode a single tone sound */
    t = 0;
    tincr = 2 * M_PI * 440.0 / c->sample_rate;
    for(i=0;i<200;i++) {
        for(j=0;j<frame_size;j++) {
            samples[2*j] = (int)(sin(t) * 10000);
            samples[2*j+1] = samples[2*j];
            t += tincr;
        }
        /* encode the samples */
        out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
        fwrite(outbuf, 1, out_size, f);
    }
    fclose(f);
    free(outbuf);
    free(samples);

    avcodec_close(c);
    av_free(c);
}

/*
 * Audio decoding.
 */
static void audio_decode_example(const char *outfilename, const char *filename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int len;
    FILE *f, *outfile;
    uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;
    AVFrame *decoded_frame = NULL;

    av_init_packet(&avpkt);

    printf("Audio decoding\n");

    /* find the mpeg audio decoder */
    codec = avcodec_find_decoder(CODEC_ID_MP2);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);

    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
    outfile = fopen(outfilename, "wb");
    if (!outfile) {
        av_free(c);
        exit(1);
    }

    /* decode until eof */
    avpkt.data = inbuf;
    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

    while (avpkt.size > 0) {
        int got_frame = 0;

        if (!decoded_frame) {
            if (!(decoded_frame = avcodec_alloc_frame())) {
                fprintf(stderr, "out of memory\n");
                exit(1);
            }
        } else
            avcodec_get_frame_defaults(decoded_frame);

        len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
        if (len < 0) {
            fprintf(stderr, "Error while decoding\n");
            exit(1);
        }
        if (got_frame) {
            /* if a frame has been decoded, output it */
            int data_size = av_samples_get_buffer_size(NULL, c->channels,
                                                       decoded_frame->nb_samples,
                                                       c->sample_fmt, 1);
            fwrite(decoded_frame->data[0], 1, data_size, outfile);
        }
        avpkt.size -= len;
        avpkt.data += len;
        avpkt.dts =
        avpkt.pts = AV_NOPTS_VALUE;
        if (avpkt.size < AUDIO_REFILL_THRESH) {
            /* Refill the input buffer, to avoid trying to decode
             * incomplete frames. Instead of this, one could also use
             * a parser, or use a proper container format through
             * libavformat. */
            memmove(inbuf, avpkt.data, avpkt.size);
            avpkt.data = inbuf;
            len = fread(avpkt.data + avpkt.size, 1,
                        AUDIO_INBUF_SIZE - avpkt.size, f);
            if (len > 0)
                avpkt.size += len;
        }
    }

    fclose(outfile);
    fclose(f);

    avcodec_close(c);
    av_free(c);
    av_free(decoded_frame);
}

/*
 * Video encoding example
 */
static void video_encode_example(const char *filename, int codec_id)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, out_size, x, y, outbuf_size;
    FILE *f;
    AVFrame *picture;
    uint8_t *outbuf;
    int had_output=0;

    printf("Video encoding\n");

    /* find the mpeg1 video encoder */
    codec = avcodec_find_encoder(codec_id);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    picture= avcodec_alloc_frame();

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */
    c->time_base= (AVRational){1,25};
    c->gop_size = 10; /* emit one intra frame every ten frames */
    c->max_b_frames=1;
    c->pix_fmt = PIX_FMT_YUV420P;

    if(codec_id == CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);

    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    f = fopen(filename, "wb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    /* alloc image and output buffer */
    outbuf_size = 100000 + 12*c->width*c->height;
    outbuf = malloc(outbuf_size);

    /* the image can be allocated by any means and av_image_alloc() is
     * just the most convenient way if av_malloc() is to be used */
    av_image_alloc(picture->data, picture->linesize,
                   c->width, c->height, c->pix_fmt, 1);

    /* encode 1 second of video */
    for(i=0;i<25;i++) {
        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
                picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
            }
        }

        /* Cb and Cr */
        for(y=0;y<c->height/2;y++) {
            for(x=0;x<c->width/2;x++) {
                picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
                picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
            }
        }

        /* encode the image */
        out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
        had_output |= out_size;
        printf("encoding frame %3d (size=%5d)\n", i, out_size);
        fwrite(outbuf, 1, out_size, f);
    }

    /* get the delayed frames */
    for(; out_size || !had_output; i++) {
        fflush(stdout);

        out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
        had_output |= out_size;
        printf("write frame %3d (size=%5d)\n", i, out_size);
        fwrite(outbuf, 1, out_size, f);
    }

    /* add sequence end code to have a real mpeg file */
    outbuf[0] = 0x00;
    outbuf[1] = 0x00;
    outbuf[2] = 0x01;
    outbuf[3] = 0xb7;
    fwrite(outbuf, 1, 4, f);
    fclose(f);
    free(outbuf);

    avcodec_close(c);
    av_free(c);
    av_free(picture->data[0]);
    av_free(picture);
    printf("\n");
}

/*
 * Video decoding example
 */

static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
                     char *filename)
{
    FILE *f;
    int i;

    f=fopen(filename,"w");
    fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
    for(i=0;i<ysize;i++)
        fwrite(buf + i * wrap,1,xsize,f);
    fclose(f);
}

static void video_decode_example(const char *outfilename, const char *filename)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int frame, got_picture, len;
    FILE *f;
    AVFrame *picture;
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    char buf[1024];
    AVPacket avpkt;

    av_init_packet(&avpkt);

    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    printf("Video decoding\n");

    /* find the mpeg1 video decoder */
    codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    picture= avcodec_alloc_frame();

    if(codec->capabilities&CODEC_CAP_TRUNCATED)
        c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */

    /* For some codecs, such as msmpeg4 and mpeg4, width and height
       MUST be initialized there because this information is not
       available in the bitstream. */

    /* open it */
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }

    /* the codec gives us the frame size, in samples */

    f = fopen(filename, "rb");
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }

    frame = 0;
    for(;;) {
        avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
        if (avpkt.size == 0)
            break;

        /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
           and this is the only method to use them because you cannot
           know the compressed data size before analysing it.

           BUT some other codecs (msmpeg4, mpeg4) are inherently frame
           based, so you must call them with all the data for one
           frame exactly. You must also initialize 'width' and
           'height' before initializing them. */

        /* NOTE2: some codecs allow the raw parameters (frame size,
           sample rate) to be changed at any frame. We handle this, so
           you should also take care of it */

        /* here, we use a stream based decoder (mpeg1video), so we
           feed decoder and see if it could decode a frame */
        avpkt.data = inbuf;
        while (avpkt.size > 0) {
            len = avcodec_decode_video2(c, picture, &got_picture, &avpkt);
            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frame);
                exit(1);
            }
            if (got_picture) {
                printf("saving frame %3d\n", frame);
                fflush(stdout);

                /* the picture is allocated by the decoder. no need to
                   free it */
                snprintf(buf, sizeof(buf), outfilename, frame);
                pgm_save(picture->data[0], picture->linesize[0],
                         c->width, c->height, buf);
                frame++;
            }
            avpkt.size -= len;
            avpkt.data += len;
        }
    }

    /* some codecs, such as MPEG, transmit the I and P frame with a
       latency of one frame. You must do the following to have a
       chance to get the last frame of the video */
    avpkt.data = NULL;
    avpkt.size = 0;
    len = avcodec_decode_video2(c, picture, &got_picture, &avpkt);
    if (got_picture) {
        printf("saving last frame %3d\n", frame);
        fflush(stdout);

        /* the picture is allocated by the decoder. no need to
           free it */
        snprintf(buf, sizeof(buf), outfilename, frame);
        pgm_save(picture->data[0], picture->linesize[0],
                 c->width, c->height, buf);
        frame++;
    }

    fclose(f);

    avcodec_close(c);
    av_free(c);
    av_free(picture);
    printf("\n");
}

int main(int argc, char **argv)
{
    const char *filename;

    /* register all the codecs */
    avcodec_register_all();

    if (argc <= 1) {
        audio_encode_example("/tmp/test.mp2");
        audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");

        video_encode_example("/tmp/test.h264", CODEC_ID_H264);
        video_encode_example("/tmp/test.mpg", CODEC_ID_MPEG1VIDEO);
        filename = "/tmp/test.mpg";
    } else {
        filename = argv[1];
    }

    //    audio_decode_example("/tmp/test.sw", filename);
    video_decode_example("/tmp/test%d.pgm", filename);

    return 0;
}

分享到:
评论

相关推荐

    ffmpeg视频解码示例代码

    在这个“ffmpeg视频解码示例代码”中,我们主要关注的是如何使用 FFmpeg API 进行视频解码。 解码是将编码后的视频数据转换回原始像素的过程,以便播放或进一步处理。在 FFmpeg 中,这个过程涉及以下几个关键步骤:...

    ffmpeg最新源代码

    FFmpeg 是一个开源的多媒体处理框架,广泛应用于音频和视频的编码、解码、转换以及流媒体处理。...此外,FFmpeg有一个活跃的社区,提供丰富的文档、示例代码和持续的更新支持,帮助开发者解决问题和学习新技术。

    g726源代码 音频编码解码

    4. **示例代码或测试程序**:为了帮助开发者理解和使用库,源代码包可能包含一些示例程序,展示如何正确地调用编码和解码函数。 5. **编译脚本和配置文件**:为了确保源代码可以在不同平台上编译和运行,包内可能...

    ffmpeg解码器

    在"simplest_ffmpeg_decode"这个例子中,我们可以假设它包含了一个简单的FFmpeg解码示例,可能是一个命令行脚本或者源代码,演示了如何使用FFmpeg库从H.264编码的视频中解码出YUV帧。通过学习这个示例,开发者可以更...

    基于CUDA+ffmpeg+QT+QOpenGL的硬解码解决方案demo

    在本项目中,"基于CUDA+ffmpeg+QT+QOpenGL的硬解码解决方案demo" 提供了一种高效、低延迟的视频解码方法,利用现代NVIDIA显卡的硬件加速能力,结合开源多媒体处理框架ffmpeg,图形用户界面库QT以及OpenGL进行实时...

    ffmpeg源代码0.4.8

    要深入学习FFmpeg,可以先阅读源代码中的README文件,了解编译和配置步骤,然后逐步分析关键模块的代码,例如解码器、编码器和滤镜的实现。此外,通过构建和运行示例程序,可以更好地理解FFmpeg的功能和使用方法。 ...

    ffmpeg中抽取建立的进行编码、解码('h264', 'mp2', 'mpg')

    在源代码层面,项目可能包含了初始化FFmpeg上下文、打开输入/输出文件、选择合适的编码器/解码器、分配和填充AVPacket及AVFrame结构、编码/解码视频帧、以及写入输出文件等关键步骤。对于'h264'、'mp2'和'mpg'的处理...

    NVIDIA解码器代码官方示例

    在“NVIDIA解码器代码官方示例”中,我们可以通过提供的源代码和步骤,了解如何在实际应用中集成和使用NVIDIA的硬件解码功能。 这个示例包含了一套完整的流程,从编译到运行,展示了一个使用CUDA GPU进行视频解码并...

    ffmpeg 源代码(20111216)

    20111216 版本的FFmpeg源代码可能包含了当时最新的编码技术和优化,对于开发者来说,这是一个研究历史版本的好材料。如果你想要深入理解FFmpeg的工作原理,可以分析源代码中的关键函数,如解码器的`decode_frame()`...

    MPEG4编码示例源代码

    8. **编码库的使用**:这个压缩包中的"编码库源代码"可能是某种MPEG4编码库的实现,如x264、FFmpeg等。了解如何集成这些库到VC++项目中,调用其API进行编码操作,是实际开发中的重要环节。 通过研究这个MPEG4编码...

    ffmpeg+opensl的音频解码播放示例

    在提供的压缩包中,"jni"目录很可能包含了C/C++源代码,这些代码实现了FFmpeg的解码逻辑和OpenSL ES的播放接口。开发者可以通过阅读这些源码,理解如何在实际项目中集成FFmpeg和OpenSL ES。 8. 学习与实践: 这个...

    ffmpeg4+OpenCV3+VS2017 H264编解码示例

    "Demo"这个文件很可能是包含源代码和编译设置的项目文件,用于演示如何在VS2017环境中使用FFmpeg4和OpenCV3进行H264视频的编解码。开发者可以通过运行和分析这个项目,了解如何调用FFmpeg的API来读取、解码H264视频...

    基于FFMpeg的Delphi视频解码、编码、合并的例子

    在这个基于 Delphi 的项目中,我们将深入探讨如何利用 FFmpeg API 来实现视频的解码、编码和合并。 首先,让我们从视频解码开始。解码是将视频文件中的压缩数据转换为可播放的原始像素流的过程。在 Delphi 中,你...

    ffmpeg-学习资料源代码

    在“ffmpeg-学习资料源代码”这个压缩包中,包含了丰富的学习资源,如播放器和服务器等,这些都是FFmpeg应用实例的绝佳参考资料。 FFmpeg 的核心功能包括: 1. **编码**:它支持多种音频和视频编码格式,例如 H.264...

    FFmpeg_录屏_编码_转码

    `FFmpeg` 目录可能包含源代码和头文件,而 `ipch` 和 `Debug` 目录则分别用于临时文件和编译生成的调试版本二进制文件。 6. **使用示例**: 使用这个压缩包,开发者可以快速地在 VC2010 中构建一个 FFmpeg 项目,...

    FFMPEG实现视频格式转换组件-源代码

    在“18_视频转化处理”这个文件中,可能包含了实现上述过程的源代码示例。这些代码可能涵盖了从初始化FFMPEG上下文、打开输入和输出文件、配置编码器和解码器参数,到执行实际的转换操作等各个阶段。开发者可以通过...

    C++基于FFmpeg的音频解码和播放

    首先,你需要下载FFmpeg源代码并按照官方文档进行配置,以便在你的C++项目中链接所需的库。确保在配置时包含解码和播放所需的组件,如libavcodec、libavformat和libavutil。 接着,创建一个新的C++项目,并引入...

    FFmpeg4.0及源文件和示例

    FFmpeg4.0是FFmpeg项目的一个重要版本,它是一个开源的、跨平台的多媒体处理工具,涵盖了音频、视频的编码、解码、转换、流...FFmpeg4.0的源代码提供了深入学习和扩展的可能,对于多媒体开发人员来说是一份宝贵的资源。

    H264编码 VLC解码 FFMPEG

    对于开发者来说,VLC的源代码提供了一个很好的学习和研究视频解码的平台。 FFMPEG则是一个更全面的多媒体处理工具集,它不仅可以用于视频播放,还可以进行视频编码、解码、转换、流媒体传输等多种操作。FFMPEG包含...

    FFmpeg解码mp4为yuv源代码技术资料

    FFmpeg是一款强大的开源多媒体处理工具,它包含了音视频编解码、封装格式转换、流媒体处理等多种功能。...在实践中,参考FFmpeg的官方文档和示例代码,以及相关的社区资源,可以更快地理解和应用这些知识。

Global site tag (gtag.js) - Google Analytics