由于AVI格式是微软推出的,所以在Windows下操作比较容易,这里我用DirectShow读写AVI视频文件,并把所有操作封装成一个类:AVICodec。下面是类的定义:

class AVICodec
{
public:
AVICodec(){size = -1;}
AVICodec(LPCWSTR avifile);
void release();
int init_getframe();
char* getframe(unsigned int index);
int getFrame(unsigned int index);
int getFrameEnd();
void play();
private:
IGraphBuilder *pGraph;
IMediaControl *pControl;
IMediaEvent   *pEvent;
IMediaDet   *pDet;

AM_MEDIA_TYPE amMediaType;
public:
BITMAPINFOHEADER *pbih;
double fps, length;
unsigned int nFrame;
long size;
bool is_begin;
char * pBuffer;
private:
char * buf;
};

这个类目前实现两个功能:

  1. 播放AVI文件      play()
  2. 获取指定帧的数据,返回数据是RGB24格式 GetFrame()

下面给出代码:

AVICodec::AVICodec(LPCWSTR avifile)//类初始化,avifile是文件名
{
pGraph   = NULL;
pControl = NULL;
pEvent   = NULL;
size   = -1;
is_begin = false;
buf    = NULL;
HRESULT hr = CoInitialize(NULL);
if(FAILED(hr)){
   cout<<"initialize COM Library failed"<<endl;
   exit(0);
}
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                        IID_IGraphBuilder, (void **)&pGraph);
if(FAILED(hr)){
   cout<<"could not create Filter Graph Manager"<<endl;
   exit(0);
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
hr = pGraph->RenderFile(avifile, NULL);
if(FAILED(hr)){
   cout<<"open AVI file failed"<<endl;
   exit(0);
}
hr = CoCreateInstance(CLSID_MediaDet, NULL, CLSCTX_INPROC, IID_IMediaDet,
   (void **)&pDet);
if(FAILED(hr)){
   cout<<"initialize MediaDet Failed"<<endl;
   exit(0);
}
hr = pDet->put_Filename(BSTR(avifile));
if(FAILED(hr)){
   cout<<"MediaDet put file failed"<<endl;
   exit(0);
}
}

int AVICodec::init_getframe()//抓图的初始化,得到帧数,帧频等参数
{
long lStreams;
HRESULT hr = pDet->get_OutputStreams(&lStreams);
if(FAILED(hr)){
   cout<<"Failed : pDet->get_OutputStreams()"<<endl;
   return -1;
}

hr = pDet->put_CurrentStream(0);
if(FAILED(hr)){
   cout<<"Failed : pDet->put_CurrentStream()"<<endl;
   return -1;
}
hr = pDet->get_StreamMediaType(&amMediaType);
if(FAILED(hr)){
   cout<<"Failed : pDet->get_StreamMediaType()"<<endl;
}
pbih = &((VIDEOINFOHEADER *)amMediaType.pbFormat)->bmiHeader;
if(FAILED(pDet->get_FrameRate(&fps)) || FAILED(pDet->get_StreamLength(&length)))
{
   cout<<"Failed : pDet->get_FrameRate() || pDet->get_StreamLength()"<<endl;
   return -1;
}
nFrame = (unsigned int)(length * fps);
return 1;
}

int AVICodec::getFrame(unsigned int index)//抓取index帧的图像,存放在buf中
{
if(index>nFrame){
   cout<<"exceed max frame index"<<endl;
   return -1;
}
HRESULT hr;
double position = (double)(index*1.0/fps);

hr = pDet->GetBitmapBits(position,&size,NULL,pbih->biWidth,pbih->biHeight);
   if(FAILED(hr)){
    cout<<"Failed : pDet->GetBitmapBits()"<<endl;
    return -1;
   }
if(is_begin==false){
   buf = new char[size];
   memset(buf,0,size);
   is_begin = true;
}
//memset(buf,0,size);
hr = pDet->GetBitmapBits(position, NULL, buf, pbih->biWidth, pbih->biHeight);
BITMAPINFO *binfo = (BITMAPINFO *)buf;
pBuffer = buf + ((BITMAPINFO *)buf)->bmiHeader.biSize;
if(FAILED(hr)){
   cout<<"Failed : pDet->GetBitmapBits()"<<endl;
   return -1;
}
return 1;
}

int AVICodec::getFrameEnd()//抓图后释放内存
{
is_begin = false;
delete[] buf;
return 1;
}

void AVICodec::play()//播放AVI文件,文件名在类初始化时给定
{
HRESULT hr = pControl->Run();
if(SUCCEEDED(hr)){
   long evCode;
   pEvent->WaitForCompletion(INFINITE,&evCode);
}
}

void AVICodec::release()//运行完释放资源
{
pControl->Release();
pEvent->Release();
pControl->Release();
pDet->Release();
CoUninitialize();
}

转载于:https://www.cnblogs.com/carekee/articles/2369897.html

DirectShow AVI 文件操作【转】相关推荐

  1. AVI文件数据流操作

    Video for Windows (VFW)在16位Windows中就引入了,现在的很多功能被DirectX所代替或超越了.但是还是有一些用处的. Audio-video-interleaved f ...

  2. 怎样用DirectShow来压缩一个AVI文件

    原文出处:http://littleflute.blog.hexun.com/1043233_d.html 这里我们讲解怎样用DirectShow来压缩一个AVI文件.我们重点放到视频压缩,同样的方法 ...

  3. Directshow学习笔记六-----重新压缩一个AVI文件(个人学习总结,仅供参考)

    用DirectShow来压缩一个AVI文件 一. 选择一个压缩过滤器 有许多种方法可以压缩视频或者音频,比如: a. 本地DirectShow过滤器 b. 视频压缩管理编码器(VCM) c. 音频压缩 ...

  4. vc++实现avi文件的操作 用于视频解析及录制(转)

    vc++实现avi文件的操作 为了对avi进行读写,微软提供了一套API,总共50个函数,他们的用途主要有两类,一个是avi文件的操作,一类是数据流streams的操作. 1.打开和关闭文件 AVIF ...

  5. vc++实现avi文件的操作

    vc++实现avi文件的操作 为了对avi进行读写,微软提供了一套API,总共50个函数,他们的用途主要有两类,一个是avi文件的操作,一类是数据流streams的操作. 1.打开和关闭文件 AVIF ...

  6. avilib操作avi文件

    一.avilib介绍 avilib是一个使用c语言编写的库,可以很方便的对avi文件提取帧和生成avi视频文件.如下列出avilib库的代码. /** avilib.h** Copyright (C) ...

  7. 重新压缩一个AVI文件

    效果图: directshow文档中有一节关于重新压缩一个AVI,按照文章的思路: 1.选择一个压缩Filter 2.设置视频压缩属性 3.生成重新压缩graph 4.写文件 给出所有源代码(文档中已 ...

  8. AVI文件规范(更新版)

    AVI文件规范 本文主要参考了如下资料: http://blog.csdn.net/sunshine1314/archive/2007/10/14/1824432.aspx 格式规范 http://b ...

  9. 【C 语言】文件操作 ( 使用 fread 和 fwrite 实现二进制文件的拷贝 | stat 统计文件大小 | feof 判定文件结尾 )

    文章目录 一.stat 统计文件大小 二.feof 判定文件结尾 三.使用 fread 和 fwrite 实现二进制文件的拷贝 一.stat 统计文件大小 统计文件大小 , 需要借助 stat 结构体 ...

最新文章

  1. matlab读取.xyz文件及任意有间隔符数据
  2. 你真的了解实时计算吗?
  3. python判断ip能否ping通_Python实现检测服务器是否可以ping通的2种方法
  4. .NET 容器环境下创建应用 dump 文件
  5. 【机器学习】机器学习从零到掌握之九 -- 教你使用K近邻算法形成完整系统
  6. php sesssion,php sesssion原理
  7. 一次学生时代的经历,利用Python在机房杀红蜘蛛,脱离老师控制!
  8. 在【使用QNX Momentics IDE构建的(只读QNX系统)】中搭建SSH方法
  9. python编程一球从100米_Python一个球100米高空落下,每次落下后反弹高度是原高度的一半,再落下...
  10. “知识付费”的分类及传播特征
  11. WinSCP:支持与linux互传的windows端的图形化SCP
  12. 在vue项目中使用html2canvas实现保存网页为图片
  13. FinalShell SSH工具安装步骤及介绍
  14. 01-邂逅React开发
  15. 听说火狐要换Logo,网友们掀起了一场“战争”
  16. 哈尔滨工业大学计算机复试英语,考研复试 | 哈尔滨工业大学复试经验贴
  17. 高压共轨喷油泵、喷油枪200mpa燃油系统专用 格雷希尔快速连接器G60UHP-M12E-A601
  18. 分享65个NET源码,总有一款适合您
  19. 不用调用函数的情况下 作次方运算
  20. java写的麻将小游戏

热门文章

  1. 单元测试整理(一)——单元测试是什么,有什么好处
  2. FFmpeg4编程入门---视频篇
  3. 在bing中保存自己的搜索关键字.
  4. Flink ReducingState 实例
  5. html背景图与表面图不对齐,html – 将内容与背景图像对齐
  6. 如何评估工时和开发计划
  7. 微信视频号的10大引流技巧
  8. Oracle enterprise manager 13C 安装无法正常进行
  9. HarmonyOS服务开放平台全面了解
  10. 一个方便的图片加载框架——ImageViewEx