使用ffmpeg实现对h264视频解码 -- (实现了一个易于使用的c++封装库)
发布日期:2021-05-09 09:06:45 浏览次数:16 分类:博客文章

本文共 14311 字,大约阅读时间需要 47 分钟。

H264���������������������������������������ffmpeg���������������������������������h264���������������������������

������������������ffmpeg���������������������������������������������������������������������c#���������������������������������������������������������������yuv���������������������rgb������������������������rgb������������������������

���H264Decode������������������������������������������������������������c���������������������c#���������

������������������ 

������������������������������������������

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 = 1;    _pCodecContext->frame_number = 1; //���������������������      _pCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;    _pCodecContext->bit_rate = 0;    _pCodecContext->time_base.den = 25;//������      _pCodecContext->width = 0;//���������      _pCodecContext->height = 0;//���������     _pCodecContext->pix_fmt = AV_PIX_FMT_YUVJ420P;    _pCodecContext->color_range = AVCOL_RANGE_MPEG;    if (avcodec_open2(_pCodecContext, _pH264VideoDecoder, NULL) >= 0)        _pFrameYuv = av_frame_alloc();    else        return FALSE;    return TRUE;}

2 ������������������������

INT32 H264Decode::H264_PutVideoStream(char* buffer, INT32 bufferLen){    AVPacket packet = { 0 };    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) == 0)    {        int height = _pCodecContext->height;        int width = _pCodecContext->width;        if (yuFormate == 1)        {            ////������������              int yLen = height * width;            memcpy(buffer, _pFrameYuv->data[0], yLen);            int uLen = yLen / 4;            memcpy(buffer + yLen, _pFrameYuv->data[1], uLen);            int vLen = uLen;            memcpy(buffer + yLen + uLen, _pFrameYuv->data[2], vLen);            return 0;        }        else        {            ////������������              int yLen = height * width;            memcpy(buffer, _pFrameYuv->data[0], yLen);            int uLen = yLen / 4;            memcpy(buffer + yLen, _pFrameYuv->data[2], uLen);            int vLen = uLen;            memcpy(buffer + yLen + uLen, _pFrameYuv->data[1], vLen);            return 0;        }    }    return -1;}

 

 

4 ������RGB������������������������������������������������������������������������

INT32 H264Decode::H264_GetNextVideoFrame_Rgb(char* buffer, INT32 bufferLen, INT32 width, INT32 height){    if (avcodec_receive_frame(_pCodecContext, _pFrameYuv) == 0)    {        ResetRgbScale(width, height);        int n = (_out_rgb_buffer_len == bufferLen);        uint8_t * data[3];        data[0] = _pFrameYuv->data[0];        data[1] = _pFrameYuv->data[2]; //u v ������������        data[2] = _pFrameYuv->data[1];        _dst_dataTmp[0] = (uint8_t *)buffer; //���������������        int ret = sws_scale(_img_convert_ctx, (const unsigned char* const*)data, _pFrameYuv->linesize, 0, _pCodecContext->height,            _dst_dataTmp, _dst_linesize);        return 0;    }    return -1;}

 

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 = 0;        long _handleDecode = 0;        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 == 0)                return;            H264DecodeWrapper.CloseHandle(_handleDecode);            _handleDecode = 0;        }        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 = 1,        SWS_BILINEAR = 2,        SWS_BICUBIC = 4,        SWS_X = 8,        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 = 0;            height = 0;            byte[] width2 = new byte[4];            byte[] height2 = new byte[4];            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 != 0)            {                return result;            }            width = BitConverter.ToInt32(width2, 0);            height = BitConverter.ToInt32(height2, 0);            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 = 1,            Y_V_U = 2,        }    }

 

上一篇:GMap.NET实现电子围栏功能(WPF版)
下一篇:.net 平台下, Socket通讯协议中间件设计思路

发表评论

最新留言

不错!
[***.144.177.141]2025年04月10日 20时00分20秒