deinit

析构与类生命周期管理

/* deinit 只有类才可以有析构

有些操作文件,套节字等需要自己释放资源的类,需要析构

*/


class DeInitClass

{

    init()

    {

        println("Init")

    }

    

    deinit //构造又参数,括号,返回值,析构没有。

    {

        println("deinit")

    }

}


func test()

{

    var c = DeInitClass() //退出函数这个区间后,类会自动调用deinit

}


test()

#include "play_video.h" #include "tp_video.h" #define MAX_QUEUE_SIZE 20 #define SMALL_WINDOW_WIDTH 144 #define SMALL_WINDOW_HEIGHT 240 typedef struct _TP_PLAYER_CONTEXT { VIDEO_CONTEXT video_ctx; } TP_PLAYER_CONTEXT; void *video_decode_thread(void *arg) { int ret = -1; avdm_unit_t avdm_unit = {0}; VIDEO_STREAM video_stream = {0}; VIDEO_CONTEXT* video_ctx = (VIDEO_CONTEXT*)arg; DECODER_HANDLER_T *decoder_handler = NULL; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return NULL; } decoder_handler = video_ctx->decoder_handle; while (1) { if (video_ctx->video_play_end) { TP_PLAYER_ERROR("video play end, video docoder thread exit"); break; } memset(&avdm_unit, 0, sizeof(avdm_unit_t)); ret = avdm_get_next_unit(video_ctx->stream_ctx.avdm_type, &video_ctx->stream_ctx.avdm_cursor, &avdm_unit); //TP_PLAYER_ERROR("avdm_get_next_unit ret = %d", ret); if (ERR_NONE == ret || -ERR_OW_GET_LATEST == ret) { // TODO:判断第一帧是I帧, 否则丢帧 memset(&video_stream, 0, sizeof(VIDEO_STREAM)); video_stream.addr = avdm_unit.addr + sizeof(FRAME_HEAD_S); /* 需除去unit的头部 */ video_stream.stream_size = avdm_unit.len - sizeof(FRAME_HEAD_S); video_stream.pts = avdm_unit.pts; if (NULL == decoder_handler || NULL == decoder_handler->ops || NULL == decoder_handler->ops->decoder_send_stream) { TP_PLAYER_ERROR("decoder handle is wrong"); return NULL; } /* 此接口可能会阻塞 */ ret = decoder_handler->ops->decoder_send_stream(video_ctx->decoder_ctx, &video_stream); if (OK != ret) { TP_PLAYER_ERROR("decoder_send_stream failed, ret = %d", ret); } continue; } else if ((-ERR_AVDM_NOT_READY == ret) || (-ERR_FRAME_NOT_READY == ret)) { // TODO:注册回调,使用条件变量阻塞 pthread_mutex_lock(&video_ctx->stream_ctx.unit_mutex); pthread_cond_wait(&video_ctx->stream_ctx.unit_cond, &video_ctx->stream_ctx.unit_mutex); pthread_mutex_unlock(&video_ctx->stream_ctx.unit_mutex); } else { break; } } return NULL; } S32 frame_receive(VIDEO_FRAME* video_frame, void* user_data) { VIDEO_FRAME* v_frame = NULL; VIDEO_CONTEXT* video_ctx = NULL; if (NULL == video_frame || NULL == user_data) { TP_PLAYER_ERROR("video_frame or user_data is NULL"); return ERROR; } video_ctx = (VIDEO_CONTEXT*)user_data; v_frame = circular_queue_peek_writable(video_ctx->frame_queue); if (NULL == v_frame) { TP_PLAYER_ERROR("ger frame from queue is NULL"); return ERROR; } v_frame->frame = video_frame->frame; v_frame->height = video_frame->height; v_frame->width = video_frame->width; v_frame->pts = video_frame->pts; circular_queue_push(video_ctx->frame_queue); return OK; } void *video_play_thread(void *arg) { VIDEO_CONTEXT* video_ctx = (VIDEO_CONTEXT*)arg; VIDEO_FRAME* v_frame = NULL; S32 ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return NULL; } while (1) { //TP_PLAYER_ERROR("video_play_thread running, queue size:%d", circular_queue_nb_remaining(video_ctx->frame_queue)); if (video_ctx->video_play_end) { TP_PLAYER_ERROR("video play end, video play thread exit"); break; } if (circular_queue_nb_remaining(video_ctx->frame_queue) > 0) { v_frame = circular_queue_peek(video_ctx->frame_queue); ret = video_ctx->disp_handle->ops->disp_display_frame(v_frame); if (ret) { TP_PLAYER_ERROR("disp_display ERROR: %d", ret); } circular_queue_move_next(video_ctx->frame_queue); } else { usleep(1000); //TP_PLAYER_ERROR("video_play_thread running"); } } return NULL; } LOCAL int video_unit_cb(void *priv) { if (NULL == priv) { TP_PLAYER_ERROR("priv is NULL"); return ERROR; } //TP_PLAYER_ERROR("video_unit_cb in"); STREAM_CONTEXT* stream_ctx = (STREAM_CONTEXT *)priv; pthread_mutex_lock(&stream_ctx->unit_mutex); pthread_cond_signal(&stream_ctx->unit_cond); pthread_mutex_unlock(&stream_ctx->unit_mutex); return OK; } static int register_unit_callback(STREAM_CONTEXT* stream_ctx) { if (NULL == stream_ctx) { TP_PLAYER_ERROR("stream_ctx is NULL"); return ERROR; } if (ERROR == avdm_register_unit_callback(stream_ctx->avdm_type, video_unit_cb, (void *)stream_ctx)) { TP_PLAYER_ERROR("tp_player register avdm callback failed"); return ERROR; } return OK; } static int unregister_unit_callback(STREAM_CONTEXT* stream_ctx) { if (NULL == stream_ctx) { TP_PLAYER_ERROR("stream_ctx is NULL"); return ERROR; } if (ERROR == avdm_unregister_unit_callback(stream_ctx->avdm_type, video_unit_cb)) { TP_PLAYER_ERROR("tp_player unregister avdm callback failed"); return ERROR; } return OK; } static int avdm_stream_ctx_init(STREAM_CONTEXT* stream_ctx, avdm_type_t stream_type) { int ret = ERROR; if (NULL == stream_ctx) { TP_PLAYER_ERROR("stream_ctx is NULL"); return ERROR; } stream_ctx->avdm_type = stream_type; pthread_mutex_init(&stream_ctx->unit_mutex, NULL); pthread_cond_init(&stream_ctx->unit_cond, NULL); ret = register_unit_callback(stream_ctx); if (OK != ret) { TP_PLAYER_ERROR("register unit callback failed"); pthread_mutex_destroy(&stream_ctx->unit_mutex); pthread_cond_destroy(&stream_ctx->unit_cond); return ERROR; } return OK; } static int avdm_stream_ctx_deinit(STREAM_CONTEXT* stream_ctx) { if (NULL == stream_ctx) { TP_PLAYER_ERROR("stream_ctx is NULL"); return ERROR; } unregister_unit_callback(stream_ctx); pthread_mutex_destroy(&stream_ctx->unit_mutex); pthread_cond_destroy(&stream_ctx->unit_cond); return OK; } int release_video_frame(void* element, void* user_data) { VIDEO_FRAME* video_frame = NULL; VIDEO_CONTEXT* video_ctx = NULL; S32 ret = ERROR; if (NULL == element || NULL == user_data) { TP_PLAYER_ERROR("element or user_data is NULL"); return ERROR; } video_frame = (VIDEO_FRAME*)element; video_ctx = (VIDEO_CONTEXT*)user_data; ret = video_ctx->decoder_handle->ops->decoder_release_frame(video_ctx->decoder_ctx, video_frame); if (ret) { TP_PLAYER_ERROR("decoder_release_frame ERROR: %d", ret); return ret; } video_frame->frame = NULL; return ret; } int video_decoder_init(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; VIDEO_DECODE_ATTRS decoder_attrs = { .width = 480, .height = 800, .decoder_type = ENCODE_TYPE_VIDEO_H264, }; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); goto err_exit; } ret = libdecoder_init(); if (OK != ret) { TP_PLAYER_ERROR("libdecoder init failed"); goto err_exit; } video_ctx->decoder_handle = libdecoder_create_handler(); if (NULL == video_ctx->decoder_handle || NULL == video_ctx->decoder_handle->ops) { TP_PLAYER_ERROR("libdecoder_create_handler failed"); goto decoder_err; } video_ctx->decoder_ctx = video_ctx->decoder_handle->ops->decoder_init(&decoder_attrs, frame_receive, video_ctx); if (NULL == video_ctx->decoder_ctx) { TP_PLAYER_ERROR("video decoder init failed"); goto decoder_err; } video_ctx->frame_queue = circular_queue_init(release_video_frame, video_ctx, sizeof(VIDEO_FRAME), MAX_QUEUE_SIZE); if (NULL == video_ctx->frame_queue) { TP_PLAYER_ERROR("frame_queue_init failed"); goto decoder_err; } return OK; decoder_err: if (video_ctx->decoder_ctx) { video_ctx->decoder_handle->ops->decoder_destory(video_ctx->decoder_ctx); video_ctx->decoder_ctx = NULL; } if (video_ctx->decoder_handle) { libdecoder_destory_handler(video_ctx->decoder_handle); video_ctx->decoder_handle = NULL; } libdecoder_deinit(); err_exit: return ERROR; } int video_decoder_deinit(VIDEO_CONTEXT* video_ctx) { if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } /* 销毁frame_queue时会调用解码器的接口释放帧,解码器必须在frame_queue销毁后销毁 */ circular_queue_destory(video_ctx->frame_queue); if (video_ctx->decoder_ctx) { video_ctx->decoder_handle->ops->decoder_destory(video_ctx->decoder_ctx); video_ctx->decoder_ctx = NULL; } if (video_ctx->decoder_handle) { libdecoder_destory_handler(video_ctx->decoder_handle); video_ctx->decoder_handle = NULL; } libdecoder_deinit(); return ERROR; } int display_init(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } /* 视频通话时, cap的screen模块已经调用libdisp_init(),此处无需调用,或者libdisp_init中增加引用计数,若没有实现引用计数,不可调用libdisp_deinit*/ video_ctx->disp_handle = libdisp_create_handler(); if (NULL == video_ctx->disp_handle || NULL == video_ctx->disp_handle->ops) { TP_PLAYER_ERROR("libdisp_create_handler failed"); return ERROR; } ret = video_ctx->disp_handle->ops->disp_set_type(PIP_WIN_DISP_LOCAL_VIDEO_TYPE); if (ret) { TP_PLAYER_ERROR("tp_player_init ERROR: %d", ret); libdisp_destory_handler(video_ctx->disp_handle); video_ctx->disp_handle = NULL; return ERROR; } return OK; } int display_deinit(VIDEO_CONTEXT* video_ctx) { if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } /* TODO:设置屏幕显示模式? */ libdisp_destory_handler(video_ctx->disp_handle); video_ctx->disp_handle = NULL; return OK; } int video_pip_stream_start(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } if (video_ctx->avdc_handler && video_ctx->avdc_handler->ops) { ret = video_ctx->avdc_handler->ops->video_stream_start(video_ctx->avdc_handler); if (ret) { TP_PLAYER_ERROR("start local stream failed"); return ERROR; } } video_ctx->is_local_stream_open = TRUE; return OK; } int video_pip_stream_stop(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } if (video_ctx->avdc_handler && video_ctx->avdc_handler->ops) { ret = video_ctx->avdc_handler->ops->video_stream_stop(video_ctx->avdc_handler); if (ret) { TP_PLAYER_ERROR("stop local stream failed"); return ERROR; } } video_ctx->is_local_stream_open = FALSE; return OK; } static int video_pip_stream_init(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; TP_STREAM_ATTR_S video_attr = { .strm_id = STRM_ID_SCREEN_DISP, .framerate = { .low = 20, .high = 1, }, .strm_res = { .res_w = SMALL_WINDOW_WIDTH, .res_h = SMALL_WINDOW_HEIGHT, }, .strm_max_res = { .res_w = 480, .res_h = 800, } }; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } video_ctx->avdc_handler = avdc_create_video_handler(&video_attr); if (NULL == video_ctx->avdc_handler || NULL == video_ctx->avdc_handler->ops) { TP_PLAYER_ERROR("avdc_create_video_handler failed"); return ERROR; } ret = video_pip_stream_start(video_ctx); if (ret) { TP_PLAYER_ERROR("start local stream failed"); avdc_destory_handler(video_ctx->avdc_handler); video_ctx->avdc_handler = NULL; return ERROR; } return OK; } static int vidoe_pip_stream_deinit(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } ret = video_pip_stream_stop(video_ctx); if (ret) { TP_PLAYER_ERROR("stop local stream failed"); return ERROR; } if (video_ctx->avdc_handler) { avdc_destory_handler(video_ctx->avdc_handler); video_ctx->avdc_handler = NULL; } return OK; } int create_video_decode_thread(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } ret = avdm_stream_ctx_init(&video_ctx->stream_ctx, AVDM_TYPE_VIDEO_CALL); if (OK != ret) { TP_PLAYER_ERROR("register unit callback failed"); return ret; } ret = video_decoder_init(video_ctx); if (OK != ret) { TP_PLAYER_ERROR("decoder init failed"); avdm_stream_ctx_deinit(&video_ctx->stream_ctx); return ret; } if (0 != pthread_create(&video_ctx->decoder_pid, NULL, video_decode_thread, video_ctx)) { TP_PLAYER_ERROR("pthread_create video_decode_thread failed"); video_decoder_deinit(video_ctx); avdm_stream_ctx_deinit(&video_ctx->stream_ctx); return ERROR; } return OK; } int create_video_display_thread(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } ret = display_init(video_ctx); if (OK != ret) { TP_PLAYER_ERROR("frame display init failed"); return ERROR; } if (0 != pthread_create(&video_ctx->play_pid, NULL, video_play_thread, video_ctx)) { TP_PLAYER_ERROR("pthread_create video_play_thread failed"); display_deinit(video_ctx); return ERROR; } return OK; } int video_play_init(VIDEO_CONTEXT* video_ctx) { int ret = ERROR; if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } video_ctx->video_play_end = FALSE; ret = create_video_decode_thread(video_ctx); if (OK != ret) { TP_PLAYER_ERROR("video decoder init failed"); return ERROR; } ret = create_video_display_thread(video_ctx); if (OK != ret) { TP_PLAYER_ERROR("video decoder init failed"); video_ctx->video_play_end = TRUE; pthread_join(video_ctx->decoder_pid, NULL); video_decoder_deinit(video_ctx); avdm_stream_ctx_deinit(&video_ctx->stream_ctx); return ERROR; } /* 初始化用于画中画的本地视频流 */ ret = video_pip_stream_init(video_ctx); if (ret) { TP_PLAYER_ERROR("pip stream init failed"); video_ctx->video_play_end = TRUE; pthread_join(video_ctx->decoder_pid, NULL); pthread_join(video_ctx->play_pid, NULL); /* 解码线程和播放线程都用到了用于缓存解码帧的队列,必须等两个线程都退出后再销毁解码器相关资源 */ video_decoder_deinit(video_ctx); avdm_stream_ctx_deinit(&video_ctx->stream_ctx); display_deinit(video_ctx); return ERROR; } return OK; } int video_play_deinit(VIDEO_CONTEXT* video_ctx) { if (NULL == video_ctx) { TP_PLAYER_ERROR("video_ctx is NULL"); return ERROR; } video_ctx->video_play_end = TRUE; vidoe_pip_stream_deinit(video_ctx); pthread_join(video_ctx->decoder_pid, NULL); pthread_join(video_ctx->play_pid, NULL); /* 解码线程和播放线程都用到了用于缓存解码帧的队列,必须等两个线程都退出后再销毁解码器和队列 */ video_decoder_deinit(video_ctx); avdm_stream_ctx_deinit(&video_ctx->stream_ctx); display_deinit(video_ctx); return OK; }解释代码
09-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值