Multimedia programming--ios video image Drawing Tool class.

Source: Internet
Author: User

Video-level image rendering on iOS

Image drawing on iOS is usually UIView's drawrect function, but this function is triggered asynchronously and executed by the main thread. Although it is possible to achieve the effect of active drawing by a certain skill:

1, pass the image to UIView cache.

2. Then call UIView's setneeddisplay to overwrite the redraw flag.

(The above two steps is to say that the image is dropped to UIView, let it draw itself, but the timing is not controllable, sometimes we need it to draw immediately, and sometimes we need to know when it is finished, we need the following two steps)

3. Call UIView's perfromonmainthread last parameter in the playback thread Waitutildone = True to execute a custom function such as Mydrawimage

4, Mydrawimage call "Nsrunloop Mainloop" Run .... (Perform a message pump)

(This calls the perfromonmainthread where it will block, knowing that the actual drawing is complete.) )



But this way of simulating the synchronous way of drawing knowledge waits for the main thread to draw complete, and if extended to a multi-frame cache is cumbersome, and UIView must inherit and then rewrite.

The following attached code is based on similar ideas, but is based on the calayer completion of the rendering tool class, synchronous and asynchronous switching only need to change the parameters of Waitutildone.


The actual test frame rate can reach about 25 (ipad mini1), if the machine better speed should be faster.


Header file


#import <Foundation/Foundation.h> #import <GLKit/GLKit.h> #import <stdint.h>/*  render video with RGB RGB only RGB 32bit format. */@interface tkvideoplayer:nsobject-(BOOL) Create: (uiview*) Target width: (uint16_t) Width height: (uint16_t) height Frate: (float) frate;-(bool) destory;-(BOOL) Update: (uint8_t*) buf len: (uint32_t) Len;-(bool) Start;-(bool) stop; @en D

Implementation file


tkvideoplayer.m//flvplayer////Created by Administrator on 14-7-11.//Copyright (c) 2014 Trustsky. All rights reserved.//#import "TKVideoPlayer.h" #import "TKTimer.h" #import "TKTimer2.h" #import "TKLock.h" #import "    TKTicker.h "#include <queue> #define Tkvideo_frame_cache_count 8@interface Tkvideoplayer () {uiview* _view    ;    float _frate;    uint16_t _width;        uint16_t _height;    uint8_t* _buffer;        uint32_t _length;        Tktimer2* _timer;        BOOL _state;    Tklock* _lockemptyqueue;        Tklock* _lockfilledqueue;    Std::queue<uint8_t*> _fmemptyqueue;        Std::queue<uint8_t*> _fmfiledqueue;        uint8_t* _fmbuffr[tkvideo_frame_cache_count];    dispatch_semaphore_t _sgempty; dispatch_semaphore_t _sgfilled;} @end @implementation tkvideoplayer-(BOOL) Create: (uiview*) Target width: (uint16_t) Width height: (uint16_t) Height frAte: (float) frate;    {Self->_view = target;    Self->_width = width;    Self->_height = height;    Self->_frate = Frate;        Self->_length = width * Height * 4;    Self->_view.layer.delegate = self;    self->_sgfilled = Dispatch_semaphore_create (Tkvideo_frame_cache_count);        Self->_sgempty = Dispatch_semaphore_create (Tkvideo_frame_cache_count);        for (int idx=0; idx<tkvideo_frame_cache_count; idx++) {_fmbuffr[idx] = (uint8_t*) malloc (_length);        _fmemptyqueue.push (_fmbuffr[idx]);    Dispatch_semaphore_wait (_sgfilled, dispatch_time_forever);    } self->_lockfilledqueue = [[Tklock alloc] init];        [Self->_lockfilledqueue Open];    Self->_lockemptyqueue = [[Tklock alloc] init];    [Self->_lockemptyqueue Open]; return true;}    -(bool) destory{self->_view.layer.delegate = nil;        Self->_view = nil;        Self->_buffer = NULL; for (int idx=0; Idx<tkvideo_frame_cache_couNT;        idx++) {free (_fmbuffr[idx]);    _FMBUFFR[IDX] = NULL;    } [Self->_lockfilledqueue close];    [Self->_lockfilledqueue release];        Self->_lockfilledqueue = nil;    [Self->_lockemptyqueue Close];    [Self->_lockemptyqueue release];        Self->_lockemptyqueue = nil;    int lastCount = Tkvideo_frame_cache_count-_fmemptyqueue.size ()-_fmfiledqueue.size ();    for (int idx=0; idx<_fmemptyqueue.size () +lastcount; idx++) dispatch_semaphore_signal (self->_sgfilled);        for (int idx=0; idx<_fmfiledqueue.size () +lastcount; idx++) dispatch_semaphore_signal (self->_sgempty);    Dispatch_release (self->_sgfilled);        self->_sgfilled = nil;    Dispatch_release (Self->_sgempty);        Self->_sgempty = nil; return true;}        -(void) Drawlayer: (Calayer *) layer Incontext: (cgcontextref) context{//Calculate the center size of the image cgrect frame = [layer bounds];    float Scalew = frame.size.width/_width; float Scaleh = Frame.size.height/_height; Float scale = Scalew < Scaleh?    Scalew:scaleh;    float image_width = _width * scale;        float image_height = _height * scale; CGRect rect = CGRectMake ((frame.size.width-image_width)/2, (Frame.size.height-image_height)/2, Image_width, Image_        height); if (_state && _buffer) {Cgdataproviderref Provider = Cgdataprovidercreatewithdata (NULL, _buffer, _length        , NULL);        Cgcolorspaceref colorspaceref = Cgcolorspacecreatedevicergb (); Cgimageref imageref = cgimagecreate (_width, _height, 8, 4 * _width, Colorspaceref, Kcgbitmapbyteorder32little|kcgimag                Ealphafirst, provider, NULL, NO, Kcgrenderingintentdefault);        CGCONTEXTTRANSLATECTM (context, 0.0, frame.size.height);        CGCONTEXTSCALECTM (Context, 1.0,-1.0);                Cgcontextdrawimage (context, rect, imageref);        Cgimagerelease (IMAGEREF);        Cgcolorspacerelease (COLORSPACEREF);     Cgdataproviderrelease (provider);           NSLog (@ "Drawlayer time Tick =%u.", get_tick32 ());        } else {Cgcontextsetrgbfillcolor (context, 0, 0, 0, 1);    Cgcontextfillrect (context, frame); }}-(BOOL) Update: (uint8_t*) buf len: (uint32_t) len{if (_state) {dispatch_semaphore_wait (_sgempty, dispatch_t                IME (Dispatch_time_now, nsec_per_msec* 100));        [_lockemptyqueue Lock];            if (_fmemptyqueue.size () = = 0) {[_lockemptyqueue unlock];        return true;        } uint8_t* Cachebuf = _fmemptyqueue.front ();        _fmemptyqueue.pop ();                [_lockemptyqueue unlock];                memcpy (Cachebuf, buf, Len);        [_lockfilledqueue Lock];        _fmfiledqueue.push (CACHEBUF);                [_lockfilledqueue unlock];    Dispatch_semaphore_signal (self->_sgfilled); } return true; -(void) timer_call{if (_state) {dispatch_semaphore_wait (self->_sgfilled, Dispatch_time (dispatch_time_now , nsec_per_msec*100)); such asWait 100 milliseconds [_lockfilledqueue lock];            if (_fmfiledqueue.size () = = 0) {[_lockfilledqueue unlock];        return;        } uint8_t* Cachebuf = _fmfiledqueue.front ();        _fmfiledqueue.pop ();                [_lockfilledqueue unlock]; [Self Performselectoronmainthread: @selector (timerdrawframe:) Withobject:[nsnumber Numberwith    Unsignedlonglong: (uint64_t) cachebuf] waituntildone:false];        }}-(void) Timerdrawframe: (nsnumber*) bufnumber{Self->_buffer = (uint8_t*) bufnumber.unsignedlonglongvalue;        if (_state && _buffer) {[Self->_view.layer setneedsdisplay];                [Self->_view.layer display];        [_lockemptyqueue Lock];        _fmemptyqueue.push (Self->_buffer);                [_lockemptyqueue unlock];    Dispatch_semaphore_signal (Self->_sgempty);        } else {[Self->_view.layer setneedsdisplay]; [self->_view.layer Display]; }}-(BOOL) clear{[self performselectoronmainthread: @selector (timerdrawframe:) withobject:[ns        Number Numberwithunsignedlonglong:null] waituntildone:true]; return true;}        -(BOOL) start{if (_timer = = nil) {_timer = [[TKTimer2 alloc] init];        _timer.delay = 1000/_frate;        _timer.objcall = self;        _timer.selcall = @selector (Timer_call);        [_timer start];    _state = true; } return true;        -(BOOL) stop{if (_timer) {_state = false;        [_timer stop];    [Self clear]; } return true; @end


There's a tktimer timer in there.


The header file for the timer is like this

@interface Tktimer2:nsobject@property (assign, nonatomic) ID        objcall; @property (assign, nonatomic) SEL       Selcall; @property (assign, nonatomic) uint32_t  delay;-(void) start;-(void) stop; @end

Set the ID of the callback + SEL and then set the delay millisecond unit, after the call to start, the Id+sel will be executed repeatedly. I still research that kind of timing effect is accurate, so do not send up to mislead everyone, we realize it


and a tklock.


#import <Foundation/Foundation.h> @interface tklock:nsobject-(void) open;-(void) close;-(void) lock;-(void) UNL Ock;-(BOOL) Trylock: (uint32_t) tick; @end

The implementation is as follows:

#import "TKLock.h" @interface Tklock () {    dispatch_semaphore_t    _sglock;//whether the cache is empty} @end @implementation tklock-( void) open{    _sglock  = dispatch_semaphore_create (1);} -(void) close{    [self trylock:1];    Dispatch_semaphore_signal (_sglock);    Dispatch_release (_sglock);    _sglock = nil;} -(void) lock{    dispatch_semaphore_wait (_sglock, dispatch_time_forever);} -(void) unlock{    dispatch_semaphore_signal (_sglock);} -(BOOL) Trylock: (uint32_t) tick{    Long retcode = dispatch_semaphore_wait (_sglock, Dispatch_time (dispatch_time_ Now, Nsec_per_msec*tick));    return (Retcode = = 0);} @end



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.