• <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)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            項目需求開發網絡流媒體播放器,整個項目就一人開發,整個系統平臺,包括調度,存儲集群服務,影像同步導入、系統api接口、視頻查詢和播放客戶端,一切有了python就變得簡單。一個人在戰斗,還是蠻有勁道。

            pyqt開發播放界面,python用于網絡通信和粘合邏輯,ffmpeg用于解碼,google一圈試用了幾個pyffmpeg的庫,非常不理想,干脆自己做:

            采用ctypes訪問dll,測試解碼并將視頻幀轉換RGB24寫入PPM文件,imagemagick轉換為jpg,okay。。

            C動態庫
            結構定義: 
             1 #define FF_BOOL int
             2 #define FF_TRUE 1
             3 #define FF_FALSE 0
             4 
             5 typedef unsigned char  StreamByte_t;
             6 
             7 //視頻流信息
             8 struct MediaStreamInfo_t{
             9     int codec_type;
            10     int codec_id;
            11     int width;
            12     int height;
            13     int gopsize;
            14     int pixfmt;
            15     int tb_num;
            16     int tb_den;
            17     int bitrate;
            18     int frame_number;
            19     int videostream; //視頻流編號
            20 };
            21 
            22 struct MediaVideoFrame_t{
            23     StreamByte_t *    rgb24;
            24     size_t            size;
            25     int                width;
            26     int                height;
            27     unsigned int    sequence; //控制播放順序
            28     unsigned int    duration; //播放時間
            29 };
            30 
            31 struct MediaPacket_t{
            32      StreamByte_t*    data;
            33      size_t            size;
            34     AVPacket    *    pkt;
            35     int                stream;    //流編號 
            36     int                dts;
            37     int                pts;
            38     size_t            sequence;
            39     size_t            duration;
            40 
            41 };
            42 
            43 struct MediaFormatContext_t;
            44 
            45 //解碼器
            46 struct MediaCodecContext_t{
            47     AVCodecContext * codecCtx;    //AVCodecContext*
            48     AVCodec *        codec;    
            49     int                stream; //流編號
            50     AVFrame *        rgbframe24; //
            51     AVFrame*        frame;    //
            52     StreamByte_t*    buffer;
            53     size_t            bufsize;
            54     void *            user;
            55     MediaStreamInfo_t si;
            56 };
            57 
            58 struct MediaFormatContext_t{
            59     AVFormatContext * fc; //AVFormatContext* 
            60     MediaStreamInfo_t video;    //視頻信息
            61     
            62 };

            實現部分
              1 
              2 MEDIACODEC_API   FF_BOOL InitLib(){
              3     avcodec_init();
              4     av_register_all();
              5     return FF_TRUE;
              6 }
              7 
              8 MEDIACODEC_API void Cleanup(){
              9 
             10 }
             11 
             12 MEDIACODEC_API  MediaCodecContext_t* InitAvCodec(MediaStreamInfo_t* si){
             13     MediaCodecContext_t* ctx;
             14     AVCodecContext * codecCtx;
             15     
             16 
             17     codecCtx = avcodec_alloc_context();
             18     codecCtx->width = si->width;
             19     codecCtx->height = si->height;
             20     codecCtx->time_base.num = si->tb_num;
             21     codecCtx->time_base.den = si->tb_den;
             22     codecCtx->bit_rate = si->bitrate;
             23     codecCtx->frame_number = si->frame_number;
             24     codecCtx->codec_type =(AVMediaType) si->codec_type;
             25     codecCtx->codec_id = (CodecID)si->codec_id;
             26 
             27     AVCodec *codec;
             28     codec = avcodec_find_decoder(codecCtx->codec_id);
             29     if(codec == NULL){
             30         //avcodec_free_context()
             31         return NULL;
             32     }
             33     if(avcodec_open(codecCtx, codec)<0){
             34         return NULL;
             35     }
             36 
             37     ctx = new MediaCodecContext_t();
             38     ctx->codecCtx    = codecCtx;
             39     ctx->codec        = codec;
             40     ctx->stream        = si->videostream;
             41     ctx->si = *si;
             42 
             43     uint8_t *buffer;
             44     size_t numBytes;
             45     ctx->rgbframe24 = avcodec_alloc_frame();
             46     ctx->frame =  avcodec_alloc_frame();
             47 
             48     numBytes=avpicture_get_size(PIX_FMT_RGB24, codecCtx->width,codecCtx->height);
             49     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
             50     ctx->buffer = (StreamByte_t*)buffer;
             51     ctx->bufsize = numBytes;
             52 
             53     avpicture_fill((AVPicture *)ctx->rgbframe24, buffer, PIX_FMT_RGB24,codecCtx->width, codecCtx->height); // bind buffer with frame
             54 
             55     return ctx;
             56 }
             57 
             58 
             59 MEDIACODEC_API void FreeAvCodec(MediaCodecContext_t* ctx){
             60     AVCodecContext * codecCtx;
             61     AVCodec *codec;
             62     codecCtx = (AVCodecContext*) ctx->codecCtx;
             63     codec = (AVCodec*) ctx->codec;
             64     avcodec_close(codecCtx);
             65     
             66     av_free(ctx->buffer);
             67     av_free(ctx->rgbframe24);
             68     av_free(ctx->frame);
             69     delete ctx;
             70 }
             71 
             72 
             73 //圖像格式轉換
             74 int convert_picture(AVFrame *rgbframe, AVFrame *frame, int width, int height, PixelFormat format,PixelFormat toformat){
             75     struct SwsContext *sws;
             76 
             77     if (format == PIX_FMT_YUV420P){        
             78         sws = sws_getContext(width, height, format, width, height, toformat, SWS_FAST_BILINEAR, NULL, NULL, NULL);
             79         if (sws == 0){
             80             return -1;
             81         }
             82         if (sws_scale(sws, frame->data, frame->linesize, 0, height, rgbframe->data, rgbframe->linesize)){
             83             //return -1;
             84         }
             85     }else{
             86         return -1;
             87     }
             88     return 0;
             89 }
             90 
             91 MEDIACODEC_API MediaVideoFrame_t * DecodeVideoFrame(MediaCodecContext_t* ctx,MediaPacket_t* pkt){
             92     MediaVideoFrame_t * frame;
             93     
             94     if(pkt->stream != ctx->stream){
             95         return NULL;
             96     }
             97     int frameFinished;
             98     
             99     AVCodecContext* codecCtx;
            100     codecCtx = (AVCodecContext*)ctx->codecCtx;
            101 
            102     avcodec_decode_video(codecCtx, ctx->frame, &frameFinished,pkt->data, pkt->size);
            103     if( !frameFinished ){
            104         return NULL;
            105     }
            106     int r;
            107     r = convert_picture(ctx->rgbframe24,ctx->frame,codecCtx->width,codecCtx->height,codecCtx->pix_fmt,PIX_FMT_RGB24);
            108     if(r){
            109         return NULL;
            110     }
            111     // 復制一份
            112     frame = new MediaVideoFrame_t();
            113     frame->rgb24 = (StreamByte_t*)malloc(ctx->bufsize);
            114     frame->size =ctx->bufsize;
            115     memcpy(frame->rgb24,ctx->buffer,ctx->bufsize);
            116     frame->width = ctx->frame->width;
            117     frame->height = ctx->frame->height;
            118     frame->sequence = pkt->sequence;
            119     frame->duration = pkt->duration;
            120 
            121     return frame;
            122 }
            123 
            124 MEDIACODEC_API void FreeVideoFrame(MediaVideoFrame_t* frame){
            125     if(frame->rgb24){
            126         free(frame->rgb24);
            127     }
            128     delete frame;
            129 }
            130 
            131 MEDIACODEC_API MediaPacket_t * AllocPacket(){
            132     MediaPacket_t *pkt;
            133 
            134     pkt = new MediaPacket_t();
            135     pkt->pkt =new AVPacket();
            136     pkt->size = 0;
            137     pkt->data = NULL;
            138     pkt->stream = -1;
            139     return pkt;
            140 }
            141 
            142 // s - 0 : 不釋放內部的 av_free_packet(); 1 - 釋放packet內部數據
            143 MEDIACODEC_API void FreePacket(MediaPacket_t* pkt,int s){
            144     AVPacket* packet;
            145     packet = pkt->pkt;
            146     if(s){
            147         av_free_packet(packet);
            148     }
            149     delete packet;
            150     delete pkt;
            151 }
            152 
            153 
            154 MEDIACODEC_API MediaFormatContext_t* InitAvFormatContext(char * file){
            155     MediaFormatContext_t* ctx;
            156     AVFormatContext *ic;
            157     int videoStream=-1;
            158     unsigned int i;
            159     AVCodecContext *codecCtx;
            160 
            161 
            162     
            163     
            164     ic = avformat_alloc_context();
            165     if(avformat_open_input(&ic, file, NULL,NULL)!=0){
            166         avformat_free_context(ic);
            167         return NULL; 
            168     }
            169     
            170     if(av_find_stream_info(ic)<0){//查詢文件流信息
            171         avformat_free_context(ic);
            172         return NULL;
            173     }
            174     
            175     
            176     for(i=0; i < ic->nb_streams; i++){
            177         if(ic->streams[i]->codec->codec_type== CODEC_TYPE_VIDEO) {
            178             videoStream=i;
            179             break;
            180         }
            181     }
            182     if( videoStream ==-1){
            183         avformat_free_context(ic);
            184         return NULL;
            185     }
            186     codecCtx = ic->streams[videoStream]->codec;
            187 
            188     ctx = new MediaFormatContext_t();
            189     ctx->fc = ic;
            190     ctx->video.codec_type = (int)CODEC_TYPE_VIDEO;
            191     ctx->video.codec_id = (int)codecCtx->codec_id;
            192     ctx->video.bitrate = codecCtx->bit_rate;
            193     ctx->video.frame_number = codecCtx->frame_number;
            194     ctx->video.gopsize = codecCtx->gop_size;
            195     ctx->video.height = codecCtx->height;
            196     ctx->video.pixfmt = codecCtx->pix_fmt;
            197     ctx->video.tb_den = codecCtx->time_base.den;
            198     ctx->video.tb_num = codecCtx->time_base.num;
            199     ctx->video.width = codecCtx->width;
            200     ctx->video.videostream = videoStream;
            201     return ctx;
            202 }
            203 
            204 MEDIACODEC_API void FreeAvFormatContext(MediaFormatContext_t* ctx){
            205     if(ctx->fc){
            206         avformat_free_context((AVFormatContext*)ctx->fc);
            207     }
            208     delete ctx;
            209 }
            210 
            211 MEDIACODEC_API MediaPacket_t* ReadNextPacket(MediaFormatContext_t* ctx){
            212     MediaPacket_t* pkt = NULL;
            213     
            214     while(1){
            215         pkt = AllocPacket();
            216         if( pkt == NULL){
            217             return NULL;
            218         }
            219         if( av_read_frame((AVFormatContext*)ctx->fc, (AVPacket*)pkt->pkt) <0 ){
            220             FreePacket(pkt,0); //并沒有釋放內部的packet數據
            221             //printf("read_fream error!\n");
            222             return NULL;
            223         }
            224         if( ctx->video.videostream == pkt->pkt->stream_index){
            225             pkt->data = pkt->pkt->data;
            226             pkt->size = pkt->pkt->size;
            227             pkt->stream = pkt->pkt->stream_index;
            228             pkt->duration = pkt->pkt->duration;
            229             return pkt;    
            230         }        
            231         FreePacket(pkt,1);
            232     }
            233 
            234     return NULL;
            235 }
            236 
            237 MEDIACODEC_API void FlushBuffer(MediaCodecContext_t* codec){
            238     avcodec_flush_buffers(codec->codecCtx);
            239 }
            240 
            241 
            242 //跳轉到指定時間 
            243 MEDIACODEC_API int SeekToTime(MediaFormatContext_t* ctx,int timesec){
            244 //avcodec_flush_buffers(pFormatCtx->streams[video_stream]->codec);
            245     
            246     if( av_seek_frame(ctx->fc,-1,timesec*AV_TIME_BASE,AVSEEK_FLAG_BACKWARD)<0){
            247         return -1;
            248     }
            249     //avcodec_flush_buffers(ctx->streams[video_stream]->codec);
            250     return 0;
            251 }
            252 
            253 MEDIACODEC_API void ReadReset(MediaFormatContext_t* ctx){
            254     SeekToTime(ctx,0);
            255 }
            256 

            python測試代碼: 

             1 
             2 import ffmpeg
             3 
             4 
             5 def printStreamInfo(s):
             6     print s.codec_type,'codec_id:',s.codec_id,\
             7         'width:',s.width,'height:',s.height,\
             8         'gopsize:',s.gopsize,'pixfmt:',s.pixfmt,\
             9         'timebase_num:',s.tb_num,'timebase_den:',s.tb_den,\
            10         'bitrate:',s.bitrate,'framenumber:',s.frame_number,\
            11         'streamindex:',s.videostream
            12 
            13 def printFrameInfo(f):
            14     print len(f.rgb24[:f.size]),'width:',f.width,'height:',f.height,'duration:',f.duration,'size:',f.size
            15     
            16 
            17 def saveppm(f,file):
            18     fp = open(file,'wb')
            19     if not fp:
            20         return
            21     fp.write( "P6\n%d %d\n255\n"%(f.width,f.height) )
            22     fp.write(f.rgb24[:f.size])
            23     fp.close()
            24     print file
            25         
            26     
            27 ffmpeg.InitLib()
            28 fc =  ffmpeg.InitAvFormatContext('d:/movies/marieMcCray.avi')
            29 printStreamInfo(fc.contents.video)
            30 bytes=0
            31 codec = ffmpeg.InitAvCodec(fc.contents.video)
            32 print codec #apply a codec
            33 
            34 cnt=0
            35 while True:
            36     pkt = ffmpeg.ReadNextPacket(fc)
            37     if not pkt:break
            38     bytes += pkt.contents.size
            39     frame = ffmpeg.DecodeVideoFrame(codec,pkt)
            40     if frame:
            41         cnt+=1
            42         printFrameInfo(frame.contents)
            43         if cnt < 100:
            44             saveppm(frame.contents,"d:/temp4/%s_xx.ppm"%cnt)
            45             os.system('convertx %s %s'%("d:/temp4/%s_xx.ppm"%cnt,"d:/temp4/%s_xx.jpg"%cnt))
            46         ffmpeg.FreeVideoFrame(frame) #memory leak
            47     print pkt.contents.stream,pkt.contents.size,pkt.contents.duration
            48     ffmpeg.FreePacket(pkt,1)
            49 







            posted on 2012-03-15 02:01 放屁阿狗 閱讀(1546) 評論(0)  編輯 收藏 引用
            久久精品国产精品青草app| 午夜精品久久久久久毛片| 精品久久久久久中文字幕人妻最新 | 伊人久久大香线蕉综合热线| 国产精品一久久香蕉国产线看| 无码人妻久久一区二区三区蜜桃| 久久精品国产一区二区三区不卡 | 久久99精品久久久久久秒播| 丁香五月网久久综合| 国产亚洲精久久久久久无码| 精品永久久福利一区二区| 亚洲色婷婷综合久久| 久久亚洲私人国产精品vA| 久久成人国产精品| 精品久久久久久国产| 99热成人精品免费久久| 久久久久亚洲精品天堂久久久久久 | 色综合久久天天综线观看| 一本色综合久久| 亚洲AV无码1区2区久久| 国产综合久久久久| 精品久久久久久久久久中文字幕| 精品久久人人做人人爽综合| 久久久精品久久久久影院| 亚洲中文字幕无码一久久区| av午夜福利一片免费看久久| 国产精品免费久久久久影院| 欧美午夜A∨大片久久 | 国产成人无码精品久久久性色| 欧美亚洲国产精品久久| avtt天堂网久久精品| 国产成人无码精品久久久久免费 | 久久综合成人网| 亚洲中文字幕无码久久2020| 久久精品国产免费| 91麻豆国产精品91久久久| 东京热TOKYO综合久久精品| 亚洲国产成人久久综合野外| 久久精品人人做人人爽97| 久久男人AV资源网站| 91精品国产91久久久久福利 |