xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #415: ffmpeg2-v4.patch

File ffmpeg2-v4.patch, 12.0 KB (added by Antoine Martin, 8 years ago)

working ffmpeg v2 patch to apply on top of r4816

  • xpra/codecs/dec_avcodec/decoder.pyx

     
    7474        int width
    7575        int height
    7676        AVPixelFormat pix_fmt
    77         int (*get_buffer)(AVCodecContext *c, AVFrame *pic)
    78         void (*release_buffer)(AVCodecContext *avctx, AVFrame *frame)
    7977        int thread_safe_callbacks
    8078        int thread_count
    8179        int thread_type
    8280        int flags
    8381        int flags2
     82        int refcounted_frames
    8483
    8584    AVPixelFormat PIX_FMT_NONE
    8685    AVCodecID CODEC_ID_H264
     
    101100    int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
    102101                                int *got_picture_ptr, const AVPacket *avpkt) nogil
    103102
    104     #buffer management:
    105     int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic)
    106     void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)
     103    void av_frame_unref(AVFrame *frame) nogil
    107104
    108105
    109106def get_version():
     
    162159    return _CODECS
    163160
    164161
    165 #maps AVCodecContext to the Decoder that manages it
    166 #the key must be obtained using get_context_key()
    167 #The Decoder manages everything.
    168 DECODERS = {}
    169 
    170 
    171 frame_alloc_counter = AtomicInteger()
    172 
    173 #these two functions convert pointers to longs
    174 #so we can use a context or frame as a dictionary key
    175 #NOTE: we can't simply use the "Frame" pointer as key
    176 #(the one we create and pass to avcodec_decode_video2)
    177 #because avcodec will pass a different "Frame" pointing
    178 #to the same memory. So we have to use frame.data[0] instead.
    179 cdef unsigned long get_context_key(AVCodecContext *avctx):
    180     cdef unsigned long ctx_key
    181     assert avctx!=NULL, "context is not set!"
    182     ctx_key = <unsigned long> avctx
    183     return ctx_key
    184 
    185 cdef unsigned long get_frame_key(AVFrame *frame):
    186     cdef unsigned long frame_key
    187     assert frame!=NULL, "frame is not set!"
    188     frame_key = <unsigned long> frame.opaque
    189     return frame_key
    190 
    191162cdef void clear_frame(AVFrame *frame):
    192163    assert frame!=NULL, "frame is not set!"
    193164    for i in xrange(4):
    194165        frame.data[i] = NULL
    195166
    196167
    197 cdef Decoder get_decoder(AVCodecContext *avctx):
    198     cdef unsigned long ctx_key = get_context_key(avctx)
    199     global DECODERS
    200     decoder = DECODERS.get(ctx_key)
    201     assert decoder is not None, "decoder not found for context %s" % hex(ctx_key)
    202     return <Decoder> decoder
    203 
    204 
    205 
    206 cdef int avcodec_get_buffer(AVCodecContext *avctx, AVFrame *frame) with gil:
    207     """ This function overrides AVCodecContext.get_buffer:
    208         we create an AVFrameWrapper object and
    209         register it with the Decoder for this context.
    210     """
    211     global frame_alloc_counter
    212     cdef unsigned long frame_key = 0
    213     cdef AVFrameWrapper frame_wrapper
    214     cdef Decoder decoder
    215     cdef int ret
    216     decoder = get_decoder(avctx)
    217     ret = avcodec_default_get_buffer(avctx, frame)
    218     if ret==0:
    219         frame_wrapper = AVFrameWrapper()
    220         frame_wrapper.set_context(avctx, frame)
    221         frame_key = frame_alloc_counter.increase()
    222         frame.opaque = <void*> frame_key
    223         decoder.add_framewrapper(frame_wrapper, frame_key)
    224     #debug("avcodec_get_buffer(%s, %s) ret=%s, decoder=%s, frame pointer=%s",
    225     #        hex(<unsigned long> avctx), hex(frame_key), ret, decoder, hex(frame_key))
    226     return ret
    227 
    228 cdef void avcodec_release_buffer(AVCodecContext *avctx, AVFrame *frame) with gil:
    229     """ when avcodec releases the buffer,
    230         we tell the Decoder to manage it.
    231     """
    232     cdef unsigned long frame_key = get_frame_key(frame)
    233     cdef Decoder decoder                        #@DuplicatedSignature
    234     debug("avcodec_release_buffer(%s, %s) frame_key=%s", hex(<unsigned long> avctx), hex(<unsigned long> frame), hex(frame_key))
    235     decoder = get_decoder(avctx)
    236     decoder.av_free(frame_key)
    237 
    238 
    239168cdef class AVFrameWrapper:
    240169    """
    241170        Wraps an AVFrame so we can free it
     
    243172    """
    244173    cdef AVCodecContext *avctx
    245174    cdef AVFrame *frame
    246     cdef int av_freed
    247175    cdef int xpra_freed
    248176
    249177    cdef set_context(self, AVCodecContext *avctx, AVFrame *frame):
    250178        self.avctx = avctx
    251179        self.frame = frame
    252         self.av_freed = 0
    253         self.xpra_freed = 0
    254         debug("%s.set_context(%s, %s)", self, hex(<long> avctx), hex(<long> frame))
     180        debug("%s.set_context(%s, %s)", self, hex(<unsigned long> avctx), hex(<unsigned long> frame))
    255181
    256182    def __dealloc__(self):
    257         #debug("CSCImage.__dealloc__()")
    258183        #By the time this wrapper is garbage collected,
    259184        #we must have freed it!
    260         assert self.av_freed, "AVFrameWrapper falling out of scope before being freed by avcodec!"
    261         assert self.xpra_freed, "AVFrameWrapper falling out of scope before being freed by xpra!"
    262185        assert self.frame==NULL and self.avctx==NULL, "frame was freed by both, but not actually freed!"
    263186
    264187    def __str__(self):
    265188        if self.frame==NULL:
    266189            return "AVFrameWrapper(NULL)"
    267         return "AVFrameWrapper(%s)" % hex(self.get_key())
     190        return "AVFrameWrapper(%s)" % hex(<unsigned long> self.frame)
    268191
    269192    def xpra_free(self):
    270         debug("%s.xpra_free() av_freed=%s", self, self.av_freed)
    271         self.xpra_freed = 1
    272         if self.av_freed==0:
    273             return False
     193        debug("%s.xpra_free()", self)
    274194        self.free()
    275         return True
    276195
    277     def av_free(self):
    278         debug("%s.av_free() xpra_freed=%s", self, self.xpra_freed)
    279         self.av_freed = 1
    280         if self.xpra_freed==0:
    281             return False
    282         self.free()
    283         return True
    284 
    285196    cdef free(self):
    286197        debug("%s.free() context=%s, frame=%s", self, hex(<unsigned long> self.avctx), hex(<unsigned long> self.frame))
    287198        if self.avctx!=NULL and self.frame!=NULL:
    288             avcodec_default_release_buffer(self.avctx, self.frame)
     199            av_frame_unref(self.frame)
    289200            self.frame = NULL
    290201            self.avctx = NULL
    291202
    292     def get_key(self):
    293         return get_frame_key(self.frame)
    294203
    295 
    296204class AVImageWrapper(ImageWrapper):
    297205    """
    298206        Wrapper which allows us to call xpra_free on the decoder
     
    315223    def xpra_free_frame(self):
    316224        debug("AVImageWrapper.xpra_free_frame() av_frame=%s", self.av_frame)
    317225        if self.av_frame:
    318             assert self.decoder, "no decoder set!"
    319             self.decoder.xpra_free(self.av_frame.get_key())
     226            self.av_frame.xpra_free()
    320227            self.av_frame = None
    321228
    322229
     
    382289            self.clean_decoder()
    383290            return  False
    384291
     292        self.codec_ctx.refcounted_frames = 1
    385293        self.codec_ctx.width = width
    386294        self.codec_ctx.height = height
    387295        self.codec_ctx.pix_fmt = self.pix_fmt
    388         self.codec_ctx.get_buffer = avcodec_get_buffer
    389         self.codec_ctx.release_buffer = avcodec_release_buffer
     296        #self.codec_ctx.get_buffer2 = avcodec_get_buffer2
     297        #self.codec_ctx.release_buffer = avcodec_release_buffer
    390298        self.codec_ctx.thread_safe_callbacks = 1
    391299        self.codec_ctx.thread_type = 2      #FF_THREAD_SLICE: allow more than one thread per frame
    392300        self.codec_ctx.thread_count = 0     #auto
     
    408316        #(we want a weakref.WeakSet() but this is python2.7+ only..)
    409317        self.weakref_images = []
    410318        #register this decoder in the global dictionary:
    411         global DECODERS
    412         cdef unsigned long ctx_key = get_context_key(self.codec_ctx)
    413         DECODERS[ctx_key] = self
    414319        debug("dec_avcodec.Decoder.init_context(%s, %s, %s) self=%s", width, height, colorspace, self.get_info())
    415320        return True
    416321
     
    443348            if r!=0:
    444349                log.warn("error closing decoder context %s: %s", hex(<unsigned long> self.codec_ctx), self.av_error_str(r))
    445350            av_free(self.codec_ctx)
    446             global DECODERS
    447             ctx_key = get_context_key(self.codec_ctx)
    448             if ctx_key in DECODERS:
    449                 DECODERS[ctx_key] = self
    450351            self.codec_ctx = NULL
    451352        debug("clean_decoder() done")
    452353
     
    523424            len = avcodec_decode_video2(self.codec_ctx, self.frame, &got_picture, &avpkt)
    524425            free(padded_buf)
    525426        if len < 0: #for testing add: or options.get("frame", 0)%100==99:
    526             framewrapper = self.frame_error()
    527             log.warn("%s.decompress_image(%s:%s, %s) avcodec_decode_video2 failure: %s, framewrapper=%s", self, type(input), buf_len, options, self.av_error_str(len), framewrapper)
     427            self.frame_error()
     428            log.warn("%s.decompress_image(%s:%s, %s) avcodec_decode_video2 failure: %s", self, type(input), buf_len, options, self.av_error_str(len))
    528429            return None
    529430            #raise Exception("avcodec_decode_video2 failed to decode this frame and returned %s, decoder=%s" % (len, self.get_info()))
    530431
     
    575476        assert self.codec_ctx.width>=self.width, "codec width is smaller than our width: %s<%s" % (self.codec_ctx.width, self.width)
    576477        assert self.codec_ctx.height>=self.height, "codec height is smaller than our height: %s<%s" % (self.codec_ctx.height, self.height)
    577478        img = AVImageWrapper(0, 0, self.width, self.height, out, cs, 24, strides, nplanes)
    578         img.decoder = self
    579479        img.av_frame = None
    580         frame_key = get_frame_key(self.frame)
    581         framewrapper = self.get_framewrapper(frame_key)
    582         assert framewrapper is not None, "framewrapper not found for frame key %s" % frame_key
    583         #framewrapper.set_frame(self.frame)
     480        framewrapper = AVFrameWrapper()
     481        framewrapper.set_context(self.codec_ctx, self.frame)
    584482        img.av_frame = framewrapper
    585483        self.frames += 1
    586484        #add to weakref list after cleaning it up:
     
    592490
    593491
    594492    cdef AVFrameWrapper frame_error(self):
    595         cdef unsigned long frame_key                    #@DuplicatedSignature
    596         log("frame_error() frame_key=%s", hex(<unsigned long> self.frame))
    597         frame_key = get_frame_key(self.frame)
    598         framewrapper = self.get_framewrapper(frame_key, True)
    599         log("frame_error() av-freeing %s", hex(<unsigned long> self.frame), framewrapper)
    600         if framewrapper:
    601             #avcodec had allocated a buffer, make sure we don't claim to be using it:
    602             self.av_free(frame_key)
    603         return <AVFrameWrapper> framewrapper
     493        av_frame_unref(self.frame)
    604494
    605     cdef AVFrameWrapper get_framewrapper(self, frame_key, ignore_missing=False):
    606         framewrapper = self.framewrappers.get(int(frame_key))
    607         assert ignore_missing or framewrapper is not None, "frame not found for pointer %s, known frame keys=%s" % (hex(frame_key),
    608                                 [hex(x) for x in self.framewrappers.keys()])
    609         return <AVFrameWrapper> framewrapper
    610 
    611     cdef add_framewrapper(self, AVFrameWrapper frame_wrapper, unsigned long frame_key):
    612         debug("add_framewrapper(%s, %s) known frame keys: %s", frame_wrapper, hex(frame_key),
    613                                 [hex(x) for x in self.framewrappers.keys()])
    614         self.framewrappers[int(frame_key)] = frame_wrapper
    615 
    616     cdef av_free(self, unsigned long frame_key):        #@DuplicatedSignature
    617         cdef AVFrameWrapper framewrapper                #@DuplicatedSignature
    618         framewrapper = self.get_framewrapper(frame_key, True)
    619         debug("av_free(%s) framewrapper=%s", hex(frame_key), framewrapper)
    620         if framewrapper is not None and framewrapper.av_free():
    621             #frame has been freed - remove it from dict:
    622             del self.framewrappers[frame_key]
    623 
    624     def xpra_free(self, unsigned long frame_key):       #@DuplicatedSignature
    625         cdef AVFrameWrapper framewrapper                #@DuplicatedSignature
    626         framewrapper = self.get_framewrapper(frame_key)
    627         debug("xpra_free(%s) framewrapper=%s", hex(frame_key), framewrapper)
    628         if framewrapper.xpra_free():
    629             #frame has been freed - remove it from dict:
    630             del self.framewrappers[frame_key]
    631 
    632495    def get_colorspace(self):
    633496        return self.colorspace
    634497