`
huzhenyu
  • 浏览: 191820 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

h264 encode

    博客分类:
  • c++
 
阅读更多
#ifdef __cplusplus
extern "C" {
#endif
#include "libavutil/opt.h"
#include "libavcodec/avcodec.h"
#include "libavutil/audioconvert.h"
#include "libavutil/common.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"

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

//int main()
//{
//	std::cout << "Test";
//	int i = 0;
//	std::cin >> i;
//	return 0;
//}

/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt)
{
    const enum AVSampleFormat *p = codec->sample_fmts;

    while (*p != AV_SAMPLE_FMT_NONE) {
        if (*p == sample_fmt)
            return 1;
        p++;
    }
    return 0;
}

/* just pick the highest supported samplerate */
static int select_sample_rate(AVCodec *codec)
{
    const int *p;
    int best_samplerate = 0;

    if (!codec->supported_samplerates)
        return 44100;

    p = codec->supported_samplerates;
    while (*p) {
        best_samplerate = FFMAX(*p, best_samplerate);
        p++;
    }
    return best_samplerate;
}

/* select layout with the highest channel count */
static int select_channel_layout(AVCodec *codec)
{
    const uint64_t *p;
    uint64_t best_ch_layout = 0;
    int best_nb_channells   = 0;

    if (!codec->channel_layouts)
        return AV_CH_LAYOUT_STEREO;

    p = codec->channel_layouts;
    while (*p) {
        int nb_channels = av_get_channel_layout_nb_channels(*p);

        if (nb_channels > best_nb_channells) {
            best_ch_layout    = *p;
            best_nb_channells = nb_channels;
        }
        p++;
    }
    return best_ch_layout;
}

/*
 * Video encoding example
 */
static void video_encode_example(const char *filename, int codec_id)
{
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, ret, x, y, got_output;
    FILE *f;
    AVFrame *frame;
    AVPacket pkt;
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };

    printf("Encode video file %s\n", filename);

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

    c = avcodec_alloc_context3(codec);

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */
	AVRational avr;
	avr.den = 25;
	avr.num = 1;
	c->time_base = avr;
    //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 = AV_PIX_FMT_YUV420P;

    if(codec_id == AV_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);
    }

    frame = avcodec_alloc_frame();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;

    /* 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 */
    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height,
                         c->pix_fmt, 32);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw picture buffer\n");
        exit(1);
    }

    /* encode 1 second of video */
    for(i=0;i<25;i++) {
        av_init_packet(&pkt);
        pkt.data = NULL;    // packet data will be allocated by the encoder
        pkt.size = 0;

        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
                frame->data[0][y * frame->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++) {
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }

        frame->pts = i;

        /* encode the image */
        ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }

        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
    }

    /* get the delayed frames */
    for (got_output = 1; got_output; i++) {
        fflush(stdout);

        ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }

        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
    }

    /* add sequence end code to have a real mpeg file */
    fwrite(endcode, 1, sizeof(endcode), f);
    fclose(f);

    avcodec_close(c);
    av_free(c);
    av_freep(&frame->data[0]);
    avcodec_free_frame(&frame);
    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("Decode video file %s to %s\n", filename, outfilename);

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

    c = avcodec_alloc_context3(codec);
    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);
    }

    picture = avcodec_alloc_frame();
    if (!picture) {
        fprintf(stderr, "Could not allocate video frame\n");
        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);
    avcodec_free_frame(&picture);
    printf("\n");
}

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

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

    /*if (argc < 2) {
        printf("usage: %s output_type\n"
               "API example program to decode/encode a media stream with libavcodec.\n"
               "This program generates a synthetic stream and encodes it to a file\n"
               "named test.h264, test.mp2 or test.mpg depending on output_type.\n"
               "The encoded stream is then decoded and written to a raw data output\n."
               "output_type must be choosen between 'h264', 'mp2', 'mpg'\n",
               argv[0]);
        return 1;
    }
    output_type = argv[1];

    if (!strcmp(output_type, "h264")) {
        video_encode_example("test.h264", AV_CODEC_ID_H264);
    } else if (!strcmp(output_type, "mp2")) {
        audio_encode_example("test.mp2");
        audio_decode_example("test.sw", "test.mp2");
    } else if (!strcmp(output_type, "mpg")) {
        video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO);
        video_decode_example("test%02d.pgm", "test.mpg");
    } else {
        fprintf(stderr, "Invalid output type '%s', choose between 'h264', 'mp2', or 'mpg'\n",
                output_type);
        return 1;
    }*/

	video_encode_example("test.h264", AV_CODEC_ID_H264);

    return 0;
}
#ifdef __cplusplus
}
#endif

http://blog.sina.com.cn/s/blog_51a320810100abuq.html
http://blog.sina.com.cn/s/blog_53b3dc830100llwg.html
分享到:
评论

相关推荐

    h264encode_src

    "h264encode_src"这个项目显然涉及到H264编码器的源代码实现。接下来,我们将深入探讨H264编码的基本原理、相关文件的功能以及它们在编码过程中的作用。 H264,全称ITU-T H.264或MPEG-4 Part 10,是一种高效能的...

    Android H264 encode

    在Android平台上进行H.264编码涉及到许多关键知识点,这些技术主要应用于视频录制、流媒体传输以及视频会议等场景。H.264是一种高效、高质量的视频编码标准,其编码过程通常包括熵编码、变换编码、帧间预测、熵解码...

    h264-incode-and-encode.rar_H264 C语言_encode 和incode_h264 encode_

    在本文中,我们将深入探讨H264编码与解码技术,特别是在C语言环境下的实现。H264,也称为AVC(Advanced Video Coding),是目前广泛应用的视频压缩标准,广泛应用于高清视频、网络流媒体、蓝光光盘等领域。它的高效...

    android_h264_encode.rar

    "android_h264_encode.rar"这个压缩包显然包含了与Android设备上H264视频编码相关的资源和文档,让我们来深入探讨其中涉及的知识点。 首先,我们要理解H264编码。H264,也称为AVC(Advanced Video Coding),是一种...

    USB摄像头 YUV图像视频编码生成h264 encode节点的使用 app_usb_disp.zip

    配合这篇博客使用此资源https://blog.csdn.net/AIRKernel/article/details/121807558 将USB摄像头生成的YUV图像转换成H264文件输出,并可以在Ubuntu上播放此视频文件。完成对视频的压缩工作。

    H264Android-264encode

    《H264Android-264encode:深入解析Android平台上的H.264编码技术》 在当今的移动设备领域,视频编码技术扮演着至关重要的角色,尤其是在Android平台上。H.264,全称High Efficiency Video Coding(高效视频编码)...

    h264编解码算法,生成算法动态库

    标签“h264 encode decode”表明这个压缩包包含了与编码和解码相关的资源。 总的来说,H264编解码算法是现代视频处理的基础,理解和应用这一技术对于开发视频应用、流媒体服务以及各种多媒体解决方案至关重要。通过...

    h264_encode.rar

    在“h264_encode.rar”这个压缩包中,我们很可能会找到关于H264编码的详细资料,例如源代码、技术文档或者教程。 一、H264编码原理 H264编码的核心在于通过一系列复杂的算法,将原始视频数据进行压缩,以降低存储...

    WINCE上的H264编解码器

    在文件名中,“h264decode_20130410”和“h264encode_20130410”分别代表了H264解码器和编码器的特定版本,日期可能表示这些优化是在2013年4月10日完成的。这表明优化工作可能针对当时的硬件特性和软件环境进行了...

    A10_H264_Encode

    全志 a10开发板 专用的 H264 硬件 encoding 源码 H264 encoding sample source code using allwinner a10 hardware encoding function for development board

    s3c6410-h264-encode-ok.rar_encode_h264_ov9650 6410_s3c6410_s3c64

    标题中的“s3c6410-h264-encode-ok.rar_encode_h264_ov9650 6410_s3c6410_s3c64”指的是一个基于S3C6410处理器的H264编码实现,该实现已经过产品化验证,能够成功地将视频数据从OV9650摄像头采集并编码为H264格式。...

    H.264Dec-Encode

    基于ARM6410开发板的H.264硬件编解码,利用开发板提供的MFC驱动-H.264 Hardware Encode and Decode program based on ARM6410,using MFC Driver

    encode_h264_acc.zip

    `encode_h264_acc.zip`这个压缩包文件提供了实现音视频硬编码和RTMP推流的关键代码示例。接下来,我们将深入探讨其中涉及的技术点。 首先,我们要了解什么是硬编码。硬编码(Hardware Encoding)是利用设备硬件来...

    H.264Encode_Decode.rar_264 encode filter

    最新视频编码协议H.246的源代码,并配有实例,不可多得的好东西!仅供参考使用,希望能丰富你的知识

    android h264 编码 解码 encode decode模块(演示)

    在Android平台上,H264编码与解码是多媒体处理中的关键环节,广泛应用于视频通话、直播、视频会议等场景。H264是一种高效、压缩比高的视频编码标准,能够在保证画质的同时减少数据传输量,对于移动设备来说尤其重要...

    live555+ffmpegdecode+x264encode

    这里我们关注的是一个具体的实现方案——"live555+ffmpegdecode+x264encode",它涉及到了三个核心组件:live555、ffmpeg以及x264,它们分别在实时流接收、视频解码和编码环节中扮演关键角色。 1. live555:这是一个...

    windows下利用x264视频编码h264源码

    4. **编码一帧**:使用`x264_encoder_encode()`函数将YUV帧编码为NAL单元,这个函数会返回编码后的H264数据。 5. **收集NAL单元**:编码完成后,通过`x264_nal_size()`和`x264_nal_extract()`函数获取NAL单元的大小...

    decode-encode-h264-demo:编码解码h264演示golang

    【标题】"decode-encode-h264-demo:编码解码h264演示golang"涉及的关键知识点主要集中在Golang编程语言以及H264视频编解码技术上。这个项目提供了一个用Go语言实现的H264编码和解码的示例程序,帮助开发者了解和学习...

    h264 宏块级流程图MB-Encode

    本篇将基于提供的宏块级流程图MB-Encode来详细解析H.264编码过程中的关键步骤。 #### 1. 宏块类型识别与初始化 在H.264编码过程中,宏块是基本的编码单元,通常为16x16像素大小。宏块编码前首先要判断宏块类型,即...

Global site tag (gtag.js) - Google Analytics