• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            socketref,再見!高德

            https://github.com/adoggie

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              246 Posts :: 4 Stories :: 312 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(54)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            寫代碼,寫好代碼其實并不難,但如果要做好文檔,能完整闡述清楚自己的構思、想法和邏輯結構,這比較難,自己也缺少這方面的耐心。
            很多opensource的代碼根本不需要文檔也能一目了然,這是一種定力
            多年前的項目中使用到python和ffmpeg, 網絡上搜索了一下,均不能滿足自己的要求。ffmpeg的python綁定提供的均是文件級的訪問控制,也就是說沒有暴露更多的可控接口來用。
            所以還是一切都自己來做
            ffmpeg采用0.81版本以上,當時發現mov文件在0.71以下無法正常解碼,到0.81則解決了此問題。
            python包裝ffmpeg的方式很多,最好的可能就是swig,但太煩了,最后選擇ctypes來訪問ffmpeg接口。 
            如果直接使用ffmpeg的api接口也不太合適,因為要暴露很多ffmpeg的接口、數據類型、常數定義等。
            所以我是這么處理:   
              1. 編寫一個功能動態庫來包裝ffmpeg,提供基本的業務功能 ,屏蔽ffmpeg細節,這里叫ffmpeg_media_codec.dll
              2. 用ctypes包裝此ffmpeg_media_codec.dll,這里是ffmpeg.py
              3. 業務代碼使用ffmpeg.py提供的接口訪問、解碼多媒體文件 
            代碼: http://sw2us.com/static/projects/py-ffmpeg/

            ffmpeg_media_codec.dll 暴露的c接口 

             1 ffmpeg lib interface list:
             2 ===========================
             4 typedef unsigned char  StreamByte_t;
             6 struct MediaStreamInfo_t{
             7     int codec_type;
             8     int codec_id;
             9     int width;
            10     int height;
            11     int gopsize;
            12     int pixfmt;
            13     int tb_num;
            14     int tb_den;
            15     int bitrate;
            16     int frame_number;
            17     int videostream; //視頻流編號
            18 };
            19 
            20 struct MediaVideoFrame_t{
            21     StreamByte_t *    rgb24;
            22     size_t            size;
            23     int                width;
            24     int                height;
            25     unsigned int    sequence; //控制播放順序
            26     unsigned int    duration; //播放時間
            27 };
            28 
            29 struct MediaPacket_t{
            30      StreamByte_t*    data;
            31      size_t            size;
            32     AVPacket    *    pkt;
            33     int                stream;    //流編號 
            34     int                dts;
            35     int                pts;
            36     size_t            sequence;
            37     size_t            duration;
            39 };
            40 
            41 struct MediaFormatContext_t;
            42 
            43 //解碼器
            44 struct MediaCodecContext_t{
            45     AVCodecContext * codecCtx;    //AVCodecContext*
            46     AVCodec *        codec;    
            47     int                stream; //流編號
            48     AVFrame *        rgbframe24; //
            49     AVFrame*        frame;    //
            50     StreamByte_t*    buffer;
            51     size_t            bufsize;
            52     void *            user;
            53     MediaStreamInfo_t si;
            54 };
            55 
            56 struct MediaFormatContext_t{
            57     AVFormatContext * fc; //AVFormatContext* 
            58     MediaStreamInfo_t video;    //視頻信息
            60 };
            66 #ifdef __cplusplus
            67  extern "C" {  
            68 #endif
            69 
            70 int InitLib();         //初始化解碼庫
            71 void Cleanup();    //
            73 MediaCodecContext_t* InitAvCodec(MediaStreamInfo_t* si);    //根據媒體類型分配解碼器對象
            74 void FreeAvCodec(MediaCodecContext_t* codec);                  //釋放解碼器對象
            76 MediaVideoFrame_t * DecodeVideoFrame(MediaCodecContext_t* ctx,MediaPacket_t* pkt);  //送入媒體包進行解碼,返回視頻幀
            77 void FreeVideoFrame(MediaVideoFrame_t* frame);                  //釋放視頻幀
            79 MediaPacket_t * AllocPacket();                                             //分配一個流媒體包對象(用于網傳)
            80 void FreePacket(MediaPacket_t* pkt);                                    //釋放流媒體包
            82 MediaFormatContext_t* InitAvFormatContext(char * file);          //媒體文件訪問上下文,申請
            83 void FreeAvFormatContext(MediaFormatContext_t* ctx);          //釋放
            84 MediaPacket_t* ReadNextPacket(MediaFormatContext_t* ctx);   //讀媒體文件一個數據包
            85 void ReadReset(MediaFormatContext_t* ctx) ;                //重置媒體訪問讀取位置
            86 int SeekToTime(int timesec) ;                                     //跳躍到指定時間

            ffmpeg.py 包裝:

              1 import ctypes
              2 from ctypes import *

              5 _lib = cdll.LoadLibrary('ffmpeg.dll')
              6 
              7 _int_types = (c_int16, c_int32)
              8 if hasattr(ctypes, 'c_int64'):
              9     # Some builds of ctypes apparently do not have c_int64
             10     # defined; it's a pretty good bet that these builds do not
             11     # have 64-bit pointers.
             12     _int_types += (ctypes.c_int64,)
             13 for t in _int_types:
             14     if sizeof(t) == sizeof(c_size_t):
             15         c_ptrdiff_t = t
             16 
             17 class c_void(Structure):
             18     # c_void_p is a buggy return type, converting to int, so
             19     # POINTER(None) == c_void_p is actually written as
             20     # POINTER(c_void), so it can be treated as a real pointer.
             21     _fields_ = [('dummy', c_int)]

             26 class MediaStreamInfo_t(Structure):
             27     _fields_ = [
             28         ('codec_type', c_int),
             29         ('codec_id', c_int),
             30         ('width', c_int),
             31         ('height', c_int),
             32         ('gopsize', c_int),
             33         ('pixfmt', c_int),
             34         ('tb_num',c_int),
             35         ('tb_den',c_int),
             36         ('bitrate',c_int),
             37         ('frame_number',c_int),
             38         ('videostream',c_int),
             39         ('duration',c_int),
             40         ('extr',POINTER(c_char)), #解碼器 額外hash表數據
             41         ('extrsize',c_int),
             42     ]
             43 
             44 class MediaVideoFrame_t(Structure):
             45     _fields_=[
             46         ('rgb24',POINTER(c_char)),
             47         ('size',c_uint),
             48         ('width',c_int),
             49         ('height',c_int),
             50         ('sequence',c_uint),
             51         ('duration',c_uint)
             52     ]
             53     
             54 class MediaPacket_t(Structure):
             55     _fields_=[
             56         ('data',POINTER(c_char)),
             57         ('size',c_uint),
             58         ('pkt',c_char_p),
             59         ('stream',c_int),
             60         ('dts',c_int),
             61         ('pts',c_int),
             62         ('sequence',c_uint),
             63         ('duration',c_uint)
             64     ]
             65     
             66     
             67 class MediaCodecContext_t(Structure):
             68     _fields_=[
             69         ('codecCtx',c_char_p),
             70         ('codec',c_char_p),
             71         ('stream',c_int),
             72         ('rgbframe24',c_char_p),
             73         ('frame',c_char_p),
             74         ('buffer',c_char_p),
             75         ('bufsize',c_uint),
             76         ('user',c_char_p),
             77         ('si',MediaStreamInfo_t)
             78     ]    
             79     
             80 class MediaFormatContext_t(Structure):
             81     _fields_=[
             82         ('fc',c_char_p),
             83         ('video',MediaStreamInfo_t)
             84     ]
             85     
             86 InitAvCodec = _lib.InitAvCodec
             87 InitAvCodec.restype = POINTER(MediaCodecContext_t)
             88 InitAvCodec.argtypes = [POINTER(MediaStreamInfo_t)]
             89 
             90 
             91 FreeAvCodec = _lib.FreeAvCodec
             92 FreeAvCodec.restype = None
             93 FreeAvCodec.argtypes = [POINTER(MediaCodecContext_t)]
             96 DecodeVideoFrame = _lib.DecodeVideoFrame
             97 DecodeVideoFrame.restype = POINTER(MediaVideoFrame_t)
             98 DecodeVideoFrame.argtypes = [POINTER(MediaCodecContext_t),POINTER(MediaPacket_t)]
            100 FreeVideoFrame = _lib.FreeVideoFrame
            101 FreeVideoFrame.restype = None
            102 FreeVideoFrame.argtypes = [POINTER(MediaVideoFrame_t)]  
            104 AllocPacket = _lib.AllocPacket
            105 AllocPacket.restype = POINTER(MediaPacket_t)
            106 AllocPacket.argtypes = []
            109 FreePacket = _lib.FreePacket
            110 FreePacket.restype = None
            111 FreePacket.argtypes = [POINTER(MediaPacket_t),c_int]
            113 InitAvFormatContext = _lib.InitAvFormatContext
            114 InitAvFormatContext.restype = POINTER(MediaFormatContext_t)
            115 InitAvFormatContext.argtypes = [c_char_p]
            117 FreeAvFormatContext = _lib.FreeAvFormatContext
            118 FreeAvFormatContext.restype = None
            119 FreeAvFormatContext.argtypes = [POINTER(MediaFormatContext_t)]
            122 ReadNextPacket = _lib.ReadNextPacket
            123 ReadNextPacket.restype = POINTER(MediaPacket_t)
            124 ReadNextPacket.argtypes = [POINTER(MediaFormatContext_t)]
            127 ReadReset = _lib.ReadReset
            128 ReadReset.restype = None
            129 ReadReset.argtypes = [POINTER(MediaFormatContext_t)]
            130 
            131 SeekToTime = _lib.SeekToTime
            132 SeekToTime.restype = c_int
            133 SeekToTime.argtypes = [POINTER(MediaFormatContext_t),c_int]
            134 
            135 FlushBuffer = _lib.FlushBuffer
            136 FlushBuffer.restype =None
            137 FlushBuffer.argtypes = [POINTER(MediaCodecContext_t)]
            138 
            139 InitLib = _lib.InitLib
            140 InitLib.restype =None
            141 InitLib.argtypes = []
            142 
            143 Cleanup = _lib.Cleanup
            144 Cleanup.restype =None
            145 Cleanup.argtypes = []

            好了,看看如何使用這些接口 
            視頻文件播放:      http://sw2us.com/static/projects/py-ffmpeg/test_qt.py
            posted on 2014-04-14 22:35 放屁阿狗 閱讀(5848) 評論(2)  編輯 收藏 引用

            Feedback

            # re: py-ffmpeg在python中利用ctype包裝的ffmpeg以提供流控制 2014-04-14 22:37 春秋十二月
            如果要做好文檔,能完整闡述清楚自己的構思、想法和邏輯結構,這比較難
            --我非常認同這句話,作為一個真正的程序員,不僅要會寫程序,還要會寫文檔,缺一不可。  回復  更多評論
              

            # re: py-ffmpeg在python中利用ctype包裝ffmpeg 2014-04-14 23:31 放屁阿狗
            首先是心態,不要讓自己毛躁起來,還有就是環境,畢竟在國內,急功近利是一種普遍的病態  回復  更多評論
              

            性做久久久久久久久| 久久国产高潮流白浆免费观看| 国产激情久久久久久熟女老人 | 久久精品成人免费国产片小草 | 国产精品久久免费| 久久亚洲AV成人无码电影| 亚洲国产精品无码久久久蜜芽| 国产精品一区二区久久精品涩爱 | 精品国产乱码久久久久久浪潮| 久久综合狠狠色综合伊人| 久久亚洲国产欧洲精品一| 久久成人精品视频| 成人精品一区二区久久久| 久久国产午夜精品一区二区三区| 久久成人精品视频| 久久99精品久久久久久噜噜| 久久精品国产清自在天天线| 亚洲人成无码网站久久99热国产| 久久久亚洲欧洲日产国码是AV| 色综合久久久久久久久五月| 久久久久99精品成人片欧美| 2020最新久久久视精品爱| 久久精品国产亚洲AV不卡| 久久频这里精品99香蕉久| 亚洲国产精品无码久久| 91久久婷婷国产综合精品青草| 精品久久久久久久久久中文字幕 | 国产欧美一区二区久久| 国产精品久久久久久一区二区三区| 久久精品国产99国产电影网 | 99蜜桃臀久久久欧美精品网站| 99久久精品国产高清一区二区 | 2021国内精品久久久久久影院| 精品久久久久久中文字幕人妻最新| 久久最新精品国产| 亚洲精品久久久www| 国产产无码乱码精品久久鸭| 国产叼嘿久久精品久久| 久久亚洲国产成人精品性色| 久久久久这里只有精品| 国产亚洲欧美精品久久久|