原作者博客 http://blog.csdn.net/taixinlfx/article/details/7531631

项目需要,要做PC端的解码器,解H264。

一直郁闷,终于今天搞定了。记录如下:

1,找了两个网站:

http://ffdshow-tryout.sourceforge.net/wiki/devel:building 这个,是k-lite的

http://ffmpeg.zeranoe.com/builds/ 这个,是windows平台编译ffmpeg的。此为关键

仔细阅读第二个网页。

下载最新的库和代码。

然后,代码中,有一个doc/examples/decoding_encoding.c。

这个文件,简明的介绍了如何解码。

然后,将该文件中需要的部分,移植到VC中编译即可。

编译过程:
错误一:无法打开包括文件:“inttypes.h”: No such file or directory
解决方法:删除之,并在其之前添加如下代码:

#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
#      define CONFIG_WIN32
#endif
#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(EMULATE_INTTYPES)
#      define EMULATE_INTTYPES
#endif
#ifndef EMULATE_INTTYPES
#     include <inttypes.h>
#else
      typedef signed char    int8_t;
      typedef signed short int16_t;
      typedef signed int     int32_t;
      typedef unsigned char    uint8_t;
      typedef unsigned short uint16_t;
      typedef unsigned int     uint32_t;
#     ifdef CONFIG_WIN32
          typedef signed __int64     int64_t;
          typedef unsigned __int64 uint64_t;
#     else /* other OS */
          typedef signed long long     int64_t;
          typedef unsigned long long uint64_t;
#     endif /* other OS */
#endif /* EMULATE_INTTYPES */

错误二: error C3861: “UINT64_C”: 找不到标识符
解决方法:在common.h中添加如下代码:

#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

修改的部分:

1,解码器,改成CODEC_ID_H264

2,avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);这个地方需要修改。要按它的帧来读。这部分期望的做法是什么还不清楚,但按原来的读法是不行的。

其它就没啥特别的了。

把修改后的代码贴在这里:

// decoder_ffmpeg.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#ifdef __cplusplus
extern "C"{
#endif

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

#ifdef __cplusplus
}
#endif

#define INBUF_SIZE (4096)

/*
 * Video decoding example
 */

static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
                     FILE *f)
{
    int i;
 //buf += 64;
    //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);
}

static int _find_head(unsigned char *buffer, int len)
{
 int i;
 int j;
 
 for (i=512;i<len;i++)
 {
  if (buffer[i] == 0 
   && buffer[i+1] == 0
   && buffer[i+2] == 0
   && buffer[i+3] == 1)
   break;
 }
 if (i == len)
  return 0;
 if (i == 512)
  return 0;
 return i;
}
#define FILE_READING_BUFFER (1*1024*1024)
static void build_avpkt(AVPacket *avpkt, FILE *fp)
{
#if 0
 int len;
 static unsigned char buffer[INBUF_SIZE];
 len = fread(buffer, 1, INBUF_SIZE, fp);
 avpkt->data = buffer;
 avpkt->size = len;
#else
 static unsigned char buffer[1*1024*1024];
 static int readptr = 0;
 static int writeptr = 0;
 int len,toread;

int nexthead;

if (writeptr - readptr < 200 * 1024)
 {
  memmove(buffer, &buffer[readptr], writeptr - readptr);
  writeptr -= readptr;
  readptr = 0;
  toread = FILE_READING_BUFFER - writeptr;
  len = fread(&buffer[writeptr], 1, toread, fp);
  writeptr += len;
 }

nexthead = _find_head(&buffer[readptr], writeptr-readptr);
 if (nexthead == 0)
 {
  printf("failed find next head...\n");
  nexthead = writeptr - readptr;
 }

avpkt->size = nexthead;
 avpkt->data = &buffer[readptr];
 readptr += nexthead;
#endif
}

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

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");
 opts = NULL;
 //av_dict_set(&opts, "b", "2.5M", 0);
    /* find the mpeg1 video decoder */
    codec = avcodec_find_decoder(CODEC_ID_H264);
    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);
    }

fout=fopen(outfilename,"wb");
    /* 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);
  build_avpkt(&avpkt, 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);
    break;
             //   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 */
                sprintf(buf, outfilename, frame);
                pgm_save(picture->data[0], picture->linesize[0],
                         c->width, c->height, fout);
                pgm_save(picture->data[1], picture->linesize[1],
                         c->width/2, c->height/2, fout);
                pgm_save(picture->data[2], picture->linesize[2],
                         c->width/2, c->height/2, fout);
                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 */
        sprintf(buf, outfilename, frame);
        //pgm_save(picture->data[0], picture->linesize[0],
          //       c->width, c->height, fout);
                 pgm_save(picture->data[0], picture->linesize[0],c->width, c->height, fout);
    pgm_save(picture->data[1], picture->linesize[1],c->width/2, c->height/2, fout);
    pgm_save(picture->data[2], picture->linesize[2],c->width/2, c->height/2, fout);

frame++;
    }

fclose(f);
 fclose(fout);

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

int _tmain(int argc, _TCHAR* argv[])
{
 printf("hello world\n");
    avcodec_register_all();
 video_decode_example("d:\\output.yuv", "d:\\record.h264");
 return 0;
}

ffmpeg h264 解码 转相关推荐

  1. ffmpeg h264解码, 屏蔽因为网络丢包等各种原因导致的花屏帧

     ffmpeg h264解码, 屏蔽因为网络丢包等各种原因导致的花屏帧  ---->看来问题只能这样解决了,现在还要多测测,防止产生新的问题.目前来看,对现有代码没有影响,花屏的帧直接屏蔽掉了. ...

  2. ffmpeg H264 编解码配置

    ffmpeg H264编解码前面有文章介绍下,本文主要介绍一些参数配置. 编码: int InitEncoderCodec( int iWidth, int iHeight) {AVCodec * p ...

  3. linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)

    在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...

  4. FFmpeg实时解码H264

    ffmpeg的解码过程在前面已经稍微总结了下,这里主要是测试一下用ffmpeg如何进行实时的解码. 在解码之前,我们先做好准备工作,调用摄像头.编码的过程中,进行入队出队操作,出队后的数据交给解码器, ...

  5. [QT+FFMPEG]使用QT自带的MinGW编译器编译FFMPEG生成LIB库(H264解码)

    [一]软件运行环境: 操作系统:win10 QT版本:qt-opensource-windows-x86-5.9.1.exe(MinGW32 5.3.0版本) 编译工具:msys2-x86_64-20 ...

  6. 264编码基本概念 FFMpeg的解码流程

    下面转自http://topic.csdn.net/u/20081020/16/7156e0b2-dbfb-4b4f-af59-2be04cf9a420.html 的8楼 1.NAL.Slice与fr ...

  7. ffmpeg 硬解码

    ffmpeg 硬件解码 由于现在h264,h265视频的增多,分辨率增大,甚至2k,4k监控视频的增多,需要利用硬件来实现高效解码和AI识别等的情况越来越多,日益重要,显卡GPU的算力强大,可以提供更 ...

  8. h264解码之环路滤波

    代码以ffmpeg为例,h264解码代码在h264.c里. 环路滤波(Loop Filter)部分 FFmpeg的H.264解码器调用decode_slice()函数完成了解码工作.这些解码工作可以大 ...

  9. windows 编译libx264 ffmpeg H264编码

    之前用FFmpeg的情形一般是 FFMpeg 拉RTSP流 解封装,然后将读出来的packet数据交给硬件去做解码编码,现在出现了一个新的轻装要求支持FFMeg软解. 即利用FFMpeg来解码 编码, ...

最新文章

  1. linux 系统基础知识 - fdisk命令
  2. 理解Linux和其他UNIX-Like系统上的平均负载
  3. 神策数据丨IPTV/OTT 精细化运营体系构建指南
  4. 一个函数处理同个元素多个事件行为------event.type
  5. java后端概述_Java后端测试概述
  6. 使用Anaconda3安装pytorch、paddle环境并在pycharm里面进行环境测试
  7. cdcqの省选膜你赛
  8. JVM堆外内存的回收机制分析
  9. 阿里矢量图标库 - Font class 方式使用说明
  10. EXCEL密码清除——巧用RAR
  11. 华为手机流量日显示无服务器,华为手机开启了数据流量却不能上网怎么办
  12. docker技术简介
  13. python输入直角边求斜边-python 已知三条边求三角形的角度案例
  14. odi12配置mysql_Oracle Data Integrator 12c 安装(ODI安装)
  15. idea 重新拉maven依赖
  16. AHRS姿态解算说明(加速度+陀螺仪+磁力计原理及原始数据分析)
  17. 有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中,谭浩强《c语言程序设计》第六章第四题
  18. 【记录】Nginx开源版安装与部署
  19. 4.1 行列式的定义
  20. ###好好好####深度学习---多标签分类问题

热门文章

  1. ERP项目实施记录08
  2. textarea最大长度限制
  3. Android新的menu实现——ActionMode
  4. jpcap的配置方法
  5. [iCustomer] 项目技术简介
  6. 科技驱动未来:飞康如何赢得尤尼克斯的青睐?
  7. KVM基础安装,手动创建桥
  8. uva 10816 Travel in Desert(简单的好题~两种方法)
  9. UIView - CAGradientLayer
  10. 广电+央视能否有力量横扫运营商+互联网?