H264是当今流行的视频压缩格式;ffmpeg是一个开源库,实现了对h264视频文件的解压缩。

为了降低使用ffmpeg的复杂性,尽量隐藏实现细节,我写了一个封装库。c#也可以很方便的使用此库。解压后的数据可以为yuv格式,也可以为rgb格式。同时可以对rgb格式视频做缩放。

类H264Decode实现了所有解码功能。最后,再把此类封装成c函数,以便于与c#交互。

代码下载地址 https://download.csdn.net/download/qq_29939347/10674597

下面讲述一下此类的实现细节:

1 BOOL H264Decode::Init()

 初始化解码库,打开h264解码器。

BOOL H264Decode::Init()
{
if (_init)
return TRUE; _init = TRUE;
if (!_av_register)
{
_av_register = TRUE;
av_register_all();
} _pCodecContext = avcodec_alloc_context3(NULL);
_pH264VideoDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
if (_pH264VideoDecoder == NULL)
{
return FALSE;
} //初始化参数,下面的参数应该由具体的业务决定 AV_PIX_FMT_YUV420P;
_pCodecContext->time_base.num = ;
_pCodecContext->frame_number = ; //每包一个视频帧
_pCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
_pCodecContext->bit_rate = ;
_pCodecContext->time_base.den = ;//帧率
_pCodecContext->width = ;//视频宽
_pCodecContext->height = ;//视频高
_pCodecContext->pix_fmt = AV_PIX_FMT_YUVJ420P;
_pCodecContext->color_range = AVCOL_RANGE_MPEG; if (avcodec_open2(_pCodecContext, _pH264VideoDecoder, NULL) >= )
_pFrameYuv = av_frame_alloc();
else
return FALSE; return TRUE;
}

2 向解码器输入数据

INT32 H264Decode::H264_PutVideoStream(char* buffer, INT32 bufferLen)
{
AVPacket packet = { };
packet.data = (uint8_t*)buffer; //这里填入一个指向完整H264数据帧的指针
packet.size = bufferLen; //这个填入H264数据帧的大小 int ret = avcodec_send_packet(_pCodecContext, &packet);
return ret;
}

3 读取解压后的数据 yuv格式

INT32 H264Decode::H264_GetNextVideoFrame(char* buffer, INT32 bufferLen, INT32 yuFormate)
{
if (avcodec_receive_frame(_pCodecContext, _pFrameYuv) == )
{
int height = _pCodecContext->height;
int width = _pCodecContext->width; if (yuFormate == )
{
////写入数据
int yLen = height * width;
memcpy(buffer, _pFrameYuv->data[], yLen); int uLen = yLen / ;
memcpy(buffer + yLen, _pFrameYuv->data[], uLen); int vLen = uLen;
memcpy(buffer + yLen + uLen, _pFrameYuv->data[], vLen);
return ;
}
else
{
////写入数据
int yLen = height * width;
memcpy(buffer, _pFrameYuv->data[], yLen); int uLen = yLen / ;
memcpy(buffer + yLen, _pFrameYuv->data[], uLen); int vLen = uLen;
memcpy(buffer + yLen + uLen, _pFrameYuv->data[], vLen);
return ;
}
}
return -;
}

4 获取RGB格式视频;可同时,根据需要的大小,对视频做缩放。

INT32 H264Decode::H264_GetNextVideoFrame_Rgb(char* buffer, INT32 bufferLen, INT32 width, INT32 height)
{
if (avcodec_receive_frame(_pCodecContext, _pFrameYuv) == )
{
ResetRgbScale(width, height); int n = (_out_rgb_buffer_len == bufferLen); uint8_t * data[];
data[] = _pFrameYuv->data[];
data[] = _pFrameYuv->data[]; //u v 向量互换
data[] = _pFrameYuv->data[]; _dst_dataTmp[] = (uint8_t *)buffer; //少一次复制
int ret = sws_scale(_img_convert_ctx, (const unsigned char* const*)data, _pFrameYuv->linesize, , _pCodecContext->height,
_dst_dataTmp, _dst_linesize);
return ;
}
return -;
}

C语言封装接口

extern "C"
{
LibFfmpegWrapper_API INT64 H264_CreateHandle();
LibFfmpegWrapper_API INT32 H264_CloseHandle(INT64 handle); LibFfmpegWrapper_API INT32 H264_SetDefaultAlgorithm(INT32 flag);
LibFfmpegWrapper_API INT32 H264_SetAlgorithm(INT64 handle, INT32 flag); LibFfmpegWrapper_API INT32 H264_PutVideoStream(INT64 handle, char* buffer, INT32 bufferLen);
LibFfmpegWrapper_API INT32 H264_GetVideoParam(INT64 handle, INT32& width, INT32& height); LibFfmpegWrapper_API INT32 H264_GetVideoFrameSize(INT64 handle);
LibFfmpegWrapper_API INT32 H264_GetVideoFrameFormate(INT64 handle); LibFfmpegWrapper_API INT32 H264_GetNextVideoFrame(INT64 handle, char* buffer, INT32 bufferLen, INT32 yuFormate); LibFfmpegWrapper_API INT32 H264_GetVideoFrameSize_Rgb(INT64 handle);
LibFfmpegWrapper_API INT32 H264_GetNextVideoFrame_Rgb(INT64 handle, char* buffer, INT32 bufferLen); LibFfmpegWrapper_API INT32 H264_GetVideoFrameSize_Rgb2(INT64 handle,INT32 width, INT32 height);
LibFfmpegWrapper_API INT32 H264_GetNextVideoFrame_Rgb2(INT64 handle, char* buffer, INT32 bufferLen, INT32 width, INT32 height);
}

c# 调用封装

class H264Decode
{
public const int Decode_Result_OK = ; long _handleDecode = ; public static void SetDefaultAlgorithm(EN_H264Algorithm flag)
{
H264DecodeWrapper.SetDefaultAlgorithm((int)flag);
} ~H264Decode()
{
Close();
} public void Init()
{
_handleDecode = H264DecodeWrapper.CreateHandle();
} public Int32 SetAlgorithm(EN_H264Algorithm flag)
{
return H264DecodeWrapper.SetAlgorithm(_handleDecode, (int)flag);
} public void Close()
{
if (_handleDecode == )
return;
H264DecodeWrapper.CloseHandle(_handleDecode);
_handleDecode = ;
} public int PutVideoStream(byte[] buffer)
{
return PutVideoStream(buffer, buffer.Length);
} public int PutVideoStream(byte[] buffer, Int32 bufferLen)
{
return H264DecodeWrapper.PutVideoStream(_handleDecode, buffer, bufferLen);
} public int GetVideoOrgSize(out int width, out int height)
{
int result = H264DecodeWrapper.GetVideoParam(_handleDecode, out width, out height);
return result;
} public int GetVideoFrameSize()
{
int result = H264DecodeWrapper.GetVideoFrameSize(_handleDecode);
return result;
}
public AVPixelFormat GetVideoFrameFormate()
{
int result = H264DecodeWrapper.GetVideoFrameFormate(_handleDecode);
return (AVPixelFormat)result;
} public int GetNextVideoFrame(byte[] buffer, Int32 bufferLen, EN_H264_YU_Formate formate)
{
int result = H264DecodeWrapper.GetNextVideoFrame(_handleDecode, buffer, bufferLen, formate);
return result;
}
public int GetNextVideoFrame(byte[] buffer, EN_H264_YU_Formate formate)
{
int result = H264DecodeWrapper.GetNextVideoFrame(_handleDecode, buffer, buffer.Length, formate);
return result;
} public int GetVideoFrameSize_Rgb()
{
int result = H264DecodeWrapper.GetVideoFrameSize_Rgb(_handleDecode);
return result;
} public int GetNextVideoFrame_Rgb(byte[] buffer, Int32 bufferLen)
{
int result = H264DecodeWrapper.GetNextVideoFrame_Rgb(_handleDecode, buffer, bufferLen);
return result;
} public int GetVideoFrameSize_Rgb2(Int32 width, Int32 height)
{
int result = H264DecodeWrapper.GetVideoFrameSize_Rgb2(_handleDecode, width, height);
return result;
} public int GetNextVideoFrame_Rgb2(byte[] buffer, Int32 bufferLen, Int32 width, Int32 height)
{
int result = H264DecodeWrapper.GetNextVideoFrame_Rgb2(_handleDecode, buffer, bufferLen, width, height);
return result;
} } public enum EN_H264Algorithm
{
SWS_FAST_BILINEAR = ,
SWS_BILINEAR = ,
SWS_BICUBIC = ,
SWS_X = ,
SWS_POINT = 0x10,
SWS_AREA = 0x20,
SWS_BICUBLIN = 0x40,
SWS_GAUSS = 0x80,
SWS_SINC = 0x100,
SWS_LANCZOS = 0x200,
SWS_SPLINE = 0x400,
} public class H264DecodeWrapper
{
private const string DLLName = "LibFfmpegWrapper.dll"; [DllImport(DLLName, EntryPoint = "H264_CreateHandle", CallingConvention = CallingConvention.Cdecl)]
private static extern long H264_CreateHandle(); [DllImport(DLLName, EntryPoint = "H264_CloseHandle", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_CloseHandle(long handle); [DllImport(DLLName, EntryPoint = "H264_PutVideoStream", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_PutVideoStream(long handle, IntPtr buffer, Int32 bufferLen); [DllImport(DLLName, EntryPoint = "H264_GetVideoParam", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetVideoParam(long handle, IntPtr width, IntPtr height); [DllImport(DLLName, EntryPoint = "H264_GetVideoFrameSize", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetVideoFrameSize(long handle); [DllImport(DLLName, EntryPoint = "H264_GetVideoFrameFormate", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetVideoFrameFormate(long handle); [DllImport(DLLName, EntryPoint = "H264_GetNextVideoFrame", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetNextVideoFrame(long handle, IntPtr buffer, Int32 bufferLen, Int32 yuFormate); [DllImport(DLLName, EntryPoint = "H264_GetVideoFrameSize_Rgb", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetVideoFrameSize_Rgb(long handle); [DllImport(DLLName, EntryPoint = "H264_GetNextVideoFrame_Rgb", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetNextVideoFrame_Rgb(long handle, IntPtr buffer, Int32 bufferLen); [DllImport(DLLName, EntryPoint = "H264_GetVideoFrameSize_Rgb2", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetVideoFrameSize_Rgb2(long handle, Int32 width, Int32 height); [DllImport(DLLName, EntryPoint = "H264_GetNextVideoFrame_Rgb2", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_GetNextVideoFrame_Rgb2(long handle, IntPtr buffer, Int32 bufferLen, Int32 width, Int32 height); [DllImport(DLLName, EntryPoint = "H264_SetDefaultAlgorithm", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_SetDefaultAlgorithm(Int32 flag); [DllImport(DLLName, EntryPoint = "H264_SetAlgorithm", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 H264_SetAlgorithm(long handle,Int32 flag); public static long CreateHandle()
{
return H264_CreateHandle();
} public static long CloseHandle(long handle)
{
return H264_CloseHandle(handle);
} public static int PutVideoStream(long handle, byte[] buffer, Int32 bufferLen)
{
GCHandle hin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
int result = H264_PutVideoStream(handle, hin.AddrOfPinnedObject(), bufferLen);
hin.Free();
return result;
} public static int GetVideoParam(long handle, out int width, out int height)
{
width = ;
height = ;
byte[] width2 = new byte[];
byte[] height2 = new byte[]; GCHandle hin_width = GCHandle.Alloc(width2, GCHandleType.Pinned);
GCHandle hin_height = GCHandle.Alloc(height2, GCHandleType.Pinned);
int result = H264_GetVideoParam(handle, hin_width.AddrOfPinnedObject(), hin_height.AddrOfPinnedObject());
hin_width.Free();
hin_height.Free(); if (result != )
{
return result;
} width = BitConverter.ToInt32(width2, );
height = BitConverter.ToInt32(height2, );
return result;
} public static int GetVideoFrameSize(long handle)
{
int result = H264_GetVideoFrameSize(handle);
return result;
}
public static int GetVideoFrameFormate(long handle)
{
int result = H264_GetVideoFrameFormate(handle);
return result;
} public static int GetNextVideoFrame(long handle, byte[] buffer, Int32 bufferLen, EN_H264_YU_Formate formate)
{
GCHandle hin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
int result = H264_GetNextVideoFrame(handle, hin.AddrOfPinnedObject(), bufferLen, (int)formate);
hin.Free();
return result;
} public static int GetVideoFrameSize_Rgb(long handle)
{
int result = H264_GetVideoFrameSize_Rgb(handle);
return result;
} public static int GetNextVideoFrame_Rgb(long handle, byte[] buffer, Int32 bufferLen)
{
GCHandle hin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
int result = H264_GetNextVideoFrame_Rgb(handle, hin.AddrOfPinnedObject(), bufferLen);
hin.Free();
return result;
} public static int GetVideoFrameSize_Rgb2(long handle, Int32 width, Int32 height)
{
int result = H264_GetVideoFrameSize_Rgb2(handle, width, height);
return result;
} public static Int32 SetDefaultAlgorithm(Int32 flag)
{
return H264_SetDefaultAlgorithm(flag);
} public static Int32 SetAlgorithm(long handle, Int32 flag)
{
return H264_SetAlgorithm(handle,flag);
} public static int GetNextVideoFrame_Rgb2(long handle, byte[] buffer, Int32 bufferLen, Int32 width, Int32 height)
{
GCHandle hin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
int result = H264_GetNextVideoFrame_Rgb2(handle, hin.AddrOfPinnedObject(), bufferLen, width, height);
hin.Free();
return result;
} public enum EN_H264_YU_Formate
{
Y_U_V = ,
Y_V_U = ,
}
}

使用ffmpeg实现对h264视频解码 -- (实现了一个易于使用的c++封装库)的更多相关文章

  1. 基于DevExpress实现对PDF、Word、Excel文档的预览及操作处理

    http://www.cnblogs.com/wuhuacong/p/4175266.html 在一般的管理系统模块里面,越来越多的设计到一些常用文档的上传保存操作,其中如PDF.Word.Excel ...

  2. C#代码实现对HTTP POST参数进行排序

    private static string GetSortedParas(Dictionary<string, string> dic) { dic = dic.OrderBy(key = ...

  3. 在VS2015中用C++创建DLL并用C#调用且同时实现对DLL的调试

    from:http://m.blog.csdn.net/article/details?id=51075023 在VS2015中先创建C#项目,然后再创建要编写的动态库DLL项目,这样做的好处是整个解 ...

  4. 【JAVA使用XPath、DOM4J解析XML文件,实现对XML文件的CRUD操作】

    一.简介 1.使用XPath可以快速精确定位指定的节点,以实现对XML文件的CRUD操作. 2.去网上下载一个“XPath帮助文档”,以便于查看语法等详细信息,最好是那种有很多实例的那种. 3.学习X ...

  5. Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

    本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这 ...

  6. struts2视频学习笔记 22-23(基于XML配置方式实现对action的所有方法及部分方法进行校验)

    课时22 基于XML配置方式实现对action的所有方法进行校验   使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类 ...

  7. 用 Python 脚本实现对 Linux 服务器的监控

    目前 Linux 下有一些使用 Python 语言编写的 Linux 系统监控工具 比如 inotify-sync(文件系统安全监控软件).glances(资源监控工具)在实际工作中,Linux 系统 ...

  8. 在应用程序中实现对NandFlash的操作

    以TC58NVG2S3ETA00 为例: 下面是它的一些物理参数: 图一 图二 图三 图四 图五 图6-0 图6-1 说明一下,在图6-1中中间的那个布局表可以看做是实际的NandFlash一页数据的 ...

  9. JDOM方法实现对XML文件的解析

    首先要下载JDOM.jar包,下载地址:http://download.csdn.net/detail/ww6055/8880371 下载到JDOM.jar包之后导入到工程中去. 实例程序: book ...

随机推荐

  1. ORA-06553: PLS-553: character set name is not recognized, while starting Content Store

    Symptom CM-CFG-5029 Content Manager is unable to determine whether the content store is initialized. ...

  2. 1.gil全局解释器锁, 2. 死锁与递归锁 3. 信号量 4. Event事件 5. 线程queue

    gil本质就是一把互斥锁,相当于执行权限,每个进程都会存在一把gil,同一进程内的多个线程必须抢到gil 之后才能使用cpython解释器来执行自己的代码,同一进程下的多线程不能并行,但可以实现并发 ...

  3. (动态规划)Worm -- hdu -- 2151

    http://acm.hdu.edu.cn/showproblem.php?pid=2151 Worm Time Limit: 1000/1000 MS (Java/Others)    Memory ...

  4. 关于自定义脚本rc.local里开机不启动的问题--以tomcat和perl相关的脚本为例

    本文将自己遇到的一些自定义脚本加入开机启动项却不成功的问题加以说明,花费了我很长时间才得以解决,当然也多谢了自己朋友的帮忙,正是因为他们的提醒,最后才找到了解决的办法,谢谢他们!!!! 系统是cent ...

  5. java基础-day14

    第01天 java面向对象 今日内容介绍 u 接口 u 匿名对象&final u 多态 第1章   接口 1.1  接口的概述 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的 ...

  6. thrift使用总结

    转自 http://blog.csdn.net/qq_27784479/article/details/73250958 Apache Thrift软件框架用于可扩展的跨语言服务开发,简单来说就是RP ...

  7. HashMap原理、源码、实践

    HashMap是一种十分常用的数据结构,作为一个应用开发人员,对其原理.实现的加深理解有助于更高效地进行数据存取.本文所用的jdk版本为1.5. 使用HashMap <Effective JAV ...

  8. [ASE][Daily Scrum]11.05

    在昨天的课程之后经过讨论进行了初步的分工,并制定出了我们的一个两周计划. 尚没有和老师讨论,已经询问了时间没有收到回复,等老师那边讨论过后我会在更新这个部分. 第一阶段的目标是用户能够在一个空白的地图 ...

  9. SpringMVC源码分析(3)DispatcherServlet的请求处理流程

    <springmvc源码分析(2)dispatcherservlet的初始化>初始化DispatcherServlet的多个组件. 本文继续分析DispatcherServlet解析请求的 ...

  10. nips 2016 吴恩达

    一年一度的 NIPS 又来了.今年举办地是笔者最爱的欧洲城市巴塞罗那.阳光沙滩配学术,确实很爽.这次的会议的第一天开场的大部分时间安排给了 tutorial.其中人数爆满的依旧是吴恩达(AndrewN ...