You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1282 lines
39 KiB
1282 lines
39 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2009-2019. All rights reserved.
|
|
* Description: Defines avplay export function
|
|
* Author: Hisilicon
|
|
* Create: 2009-12-21
|
|
* History:
|
|
*/
|
|
#include "drv_avplay.h"
|
|
|
|
#include "drv_module_ext.h"
|
|
#include "drv_demux_struct.h"
|
|
#include "drv_sync_ext.h"
|
|
#include "drv_vdec_ext.h"
|
|
#include "drv_policy_ext.h"
|
|
|
|
#define big_endian_write(a, b) (((a) << 32) | (b))
|
|
#define DRV_AVPLAY_MAX_VIR_WIN_CNT 1
|
|
|
|
typedef enum {
|
|
AVPLAY_PARAM_INC = 0, /* 递增 */
|
|
AVPLAY_PARAM_ADD, /* 累加 */
|
|
AVPLAY_PARAM_RES /* 覆盖 */
|
|
} avplay_param_type;
|
|
|
|
typedef struct {
|
|
demux_func_export *dmx_func;
|
|
drv_vdec_export_func *vdec_func;
|
|
void *win_func;
|
|
} avplay_import_func;
|
|
|
|
typedef struct {
|
|
td_bool update;
|
|
td_u64 param;
|
|
avplay_param_type param_type;
|
|
} avplay_event_info;
|
|
|
|
typedef struct {
|
|
td_handle self;
|
|
|
|
td_handle vdec;
|
|
td_handle vid_dmx;
|
|
td_handle aud_dmx;
|
|
td_handle pcr_dmx;
|
|
td_handle win;
|
|
td_handle virtual_win[DRV_AVPLAY_MAX_VIR_WIN_CNT];
|
|
td_u8 virtual_win_cnt;
|
|
td_handle sync;
|
|
|
|
td_bool vid_enable;
|
|
td_bool aud_enable;
|
|
avplay_resolution_param res;
|
|
|
|
td_u64 event_mask; /* 一个bit对应一种事件, 用于控制是否立即上报事件, 0: disable; 1: enable */
|
|
avplay_event_info events[AVPLAY_EVENT_TYPE_MAX]; /* protected by instance->spin */
|
|
} avplay_drv_ctx;
|
|
|
|
typedef struct {
|
|
td_handle handle;
|
|
avplay_drv_ctx *ctx;
|
|
const void *unique;
|
|
td_bool wait_cond;
|
|
osal_wait wq;
|
|
avplay_drv_spin_t spin; /* used in the context of interruption */
|
|
avplay_drv_mutex_t mutex;
|
|
} avplay_drv_instance;
|
|
|
|
static td_bool g_avplay_inited = TD_FALSE;
|
|
static td_u32 g_avplay_instance_cnt = 0;
|
|
static td_u32 g_avplay_play_cnt = 0;
|
|
static avplay_drv_instance g_avplay_instance[AVPLAY_MAX_CNT];
|
|
static avplay_drv_spin_t g_avplay_spinlock;
|
|
|
|
static avplay_import_func g_avplay_import_func = {TD_NULL};
|
|
static avplay_param_type g_avplay_param_types[AVPLAY_EVENT_TYPE_MAX] = {
|
|
[AVPLAY_EVENT_VID_RENDER_UNDERLOAD] = AVPLAY_PARAM_ADD,
|
|
[AVPLAY_EVENT_VID_ERR_FRAME] = AVPLAY_PARAM_RES,
|
|
[AVPLAY_EVENT_VID_TYPE_ERR] = AVPLAY_PARAM_RES,
|
|
|
|
[AVPLAY_EVENT_VID_DECODE_FORMAT_CHANGE] = AVPLAY_PARAM_RES,
|
|
[AVPLAY_EVENT_VID_DECODE_PACKING_CHANGE] = AVPLAY_PARAM_RES,
|
|
[AVPLAY_EVENT_VID_FIRST_PTS] = AVPLAY_PARAM_RES,
|
|
[AVPLAY_EVENT_VID_SECOND_PTS] = AVPLAY_PARAM_RES,
|
|
[AVPLAY_EVENT_VID_DECODE_EOS] = AVPLAY_PARAM_RES,
|
|
|
|
[AVPLAY_EVENT_VID_NEW_DMX_IDX] = AVPLAY_PARAM_RES
|
|
};
|
|
|
|
static td_s32 drv_wakeup(avplay_drv_instance *instance);
|
|
|
|
static void ctx_init(avplay_drv_ctx *ctx, td_handle avplay)
|
|
{
|
|
td_u32 i;
|
|
|
|
ctx->self = avplay;
|
|
ctx->vdec = TD_INVALID_HANDLE;
|
|
ctx->vid_dmx = TD_INVALID_HANDLE;
|
|
ctx->aud_dmx = TD_INVALID_HANDLE;
|
|
ctx->win = TD_INVALID_HANDLE;
|
|
ctx->virtual_win_cnt = 0;
|
|
|
|
for (i = 0; i < DRV_AVPLAY_MAX_VIR_WIN_CNT; i++) {
|
|
ctx->virtual_win[i] = TD_INVALID_HANDLE;
|
|
}
|
|
|
|
ctx->sync = TD_INVALID_HANDLE;
|
|
|
|
ctx->vid_enable = TD_FALSE;
|
|
ctx->aud_enable = TD_FALSE;
|
|
|
|
ctx->res.width = 0;
|
|
ctx->res.height = 0;
|
|
ctx->res.stride = 0;
|
|
ctx->res.bit_depth = 0;
|
|
ctx->res.frm_num = 0;
|
|
ctx->res.frm_size = 0;
|
|
ctx->res.meta_size = 0;
|
|
|
|
ctx->event_mask = 0LL;
|
|
for (i = 0; i < AVPLAY_EVENT_TYPE_MAX; i++) {
|
|
ctx->events[i].update = TD_FALSE;
|
|
ctx->events[i].param = 0LL;
|
|
ctx->events[i].param_type = g_avplay_param_types[i];
|
|
}
|
|
}
|
|
|
|
static void delete_win_attach(avplay_drv_ctx *ctx)
|
|
{
|
|
td_s32 ret;
|
|
td_u8 i = 0;
|
|
ext_sys_policy_win_attach_info info;
|
|
|
|
info.source_handle = ctx->self;
|
|
if (ctx->win != TD_INVALID_HANDLE) {
|
|
info.window_handle = ctx->win;
|
|
ret = ext_drv_sys_policy_del_win_attach_info(&info);
|
|
log_when_error(ret, ext_drv_sys_del_window_attach_info);
|
|
if (ret == TD_SUCCESS) {
|
|
ctx->win = TD_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
for (; i < DRV_AVPLAY_MAX_VIR_WIN_CNT; i++) {
|
|
if (ctx->virtual_win[i] != TD_INVALID_HANDLE) {
|
|
info.window_handle = ctx->virtual_win[i];
|
|
ret = ext_drv_sys_policy_del_win_attach_info(&info);
|
|
log_when_error(ret, ext_drv_sys_del_window_attach_info);
|
|
if (ret == TD_SUCCESS) {
|
|
ctx->virtual_win[i] = TD_INVALID_HANDLE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ctx_deinit(avplay_drv_instance *instance, avplay_drv_ctx **free_ctx)
|
|
{
|
|
td_ulong flags = 0;
|
|
avplay_mutex_lock(&instance->mutex);
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx != TD_NULL) {
|
|
drv_wakeup(instance);
|
|
delete_win_attach(instance->ctx);
|
|
*free_ctx = instance->ctx;
|
|
instance->ctx = TD_NULL; /* ctx is freed outside spinlock by caller */
|
|
}
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
avplay_mutex_unlock(&instance->mutex);
|
|
}
|
|
|
|
static void instance_init(void)
|
|
{
|
|
td_u32 i = 0;
|
|
if (g_avplay_inited) {
|
|
return;
|
|
}
|
|
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
g_avplay_instance[i].handle = TD_INVALID_HANDLE;
|
|
g_avplay_instance[i].ctx = TD_NULL;
|
|
g_avplay_instance[i].unique = TD_NULL;
|
|
avplay_mutex_init(&g_avplay_instance[i].mutex);
|
|
}
|
|
|
|
g_avplay_instance_cnt = 0;
|
|
g_avplay_play_cnt = 0;
|
|
g_avplay_inited = TD_TRUE;
|
|
}
|
|
|
|
static avplay_drv_instance *instance_get(td_handle handle)
|
|
{
|
|
avplay_drv_instance *instance = TD_NULL;
|
|
td_u32 index = avplay_get_id(handle);
|
|
if (index >= AVPLAY_MAX_CNT || avplay_get_modid(handle) != SOC_ID_AVPLAY) {
|
|
ext_err_avplay("Invalid avplay handle[0x%x]\n", handle);
|
|
return TD_NULL;
|
|
}
|
|
|
|
if (!g_avplay_inited) {
|
|
ext_err_avplay("AVPLAY not inited\n");
|
|
return TD_NULL;
|
|
}
|
|
|
|
if (g_avplay_instance[index].ctx == TD_NULL) {
|
|
ext_warn_avplay("Invalid avplay handle[0x%x], instance context is NULL\n", handle);
|
|
} else if (g_avplay_instance[index].handle != handle) {
|
|
ext_err_avplay("Invalid avplay handle[0x%x], instance handle[0x%x] check failed\n",
|
|
handle, g_avplay_instance[index].handle);
|
|
} else {
|
|
instance = &g_avplay_instance[index];
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
|
|
static td_s32 instance_alloc(td_handle *handle, const void *unique, avplay_drv_ctx **external_ctx)
|
|
{
|
|
td_u32 i = 0;
|
|
if (!g_avplay_inited) {
|
|
ext_err_avplay("AVPLAY not inited\n");
|
|
return SOC_ERR_AVPLAY_DEV_NO_INIT;
|
|
}
|
|
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
if (g_avplay_instance[i].handle == TD_INVALID_HANDLE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= AVPLAY_MAX_CNT) {
|
|
ext_err_avplay("Too many avplays are created, instance cnt = %u\n", g_avplay_instance_cnt);
|
|
return SOC_ERR_AVPLAY_CREATE_ERR;
|
|
}
|
|
|
|
if (g_avplay_instance[i].ctx == TD_NULL) {
|
|
g_avplay_instance[i].ctx = *external_ctx;
|
|
*external_ctx = TD_NULL;
|
|
}
|
|
|
|
ctx_init(g_avplay_instance[i].ctx, avplay_get_handle(i));
|
|
g_avplay_instance[i].wait_cond = TD_FALSE;
|
|
|
|
g_avplay_instance_cnt++;
|
|
g_avplay_instance[i].handle = avplay_get_handle(i);
|
|
g_avplay_instance[i].unique = unique;
|
|
*handle = g_avplay_instance[i].handle;
|
|
|
|
ext_dbg_avplay("Alloc drv avplay, index = 0x%x, instance_cnt = %u\n", i, g_avplay_instance_cnt);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 instance_del(td_handle handle, avplay_drv_ctx **free_ctx)
|
|
{
|
|
td_u32 index = avplay_get_id(handle);
|
|
if (index >= AVPLAY_MAX_CNT) {
|
|
ext_err_avplay("Invalid handle, index = %u\n", index);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
ctx_deinit(&g_avplay_instance[index], free_ctx);
|
|
g_avplay_instance[index].handle = TD_INVALID_HANDLE;
|
|
g_avplay_instance[index].unique = TD_NULL;
|
|
g_avplay_instance_cnt--;
|
|
|
|
ext_dbg_avplay("Delete drv avplay, index = 0x%x\n", index);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 instance_clear(const void *unique, avplay_drv_ctx *free_ctx[], td_u32 num)
|
|
{
|
|
td_u32 i = 0;
|
|
TD_UNUSED(num);
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
if (g_avplay_instance[i].unique == unique) {
|
|
ctx_deinit(&g_avplay_instance[i], &free_ctx[i]);
|
|
g_avplay_instance[i].handle = TD_INVALID_HANDLE;
|
|
g_avplay_instance[i].unique = TD_NULL;
|
|
ext_dbg_avplay("Clear drv avplay, index = 0x%x\n", i);
|
|
}
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static void instance_deinit(avplay_drv_ctx *free_ctx[], td_u32 num)
|
|
{
|
|
td_u32 i = 0;
|
|
TD_UNUSED(num);
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
ctx_deinit(&g_avplay_instance[i], &free_ctx[i]);
|
|
osal_wait_destroy(&g_avplay_instance[i].wq);
|
|
avplay_spin_deinit(&g_avplay_instance[i].spin);
|
|
avplay_mutex_deinit(&g_avplay_instance[i].mutex);
|
|
g_avplay_instance[i].handle = TD_INVALID_HANDLE;
|
|
g_avplay_instance[i].unique = TD_NULL;
|
|
}
|
|
}
|
|
|
|
static void drv_instance_init(void)
|
|
{
|
|
td_u32 i = 0;
|
|
td_ulong flags = 0;
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
instance_init();
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
avplay_spin_init(&g_avplay_instance[i].spin);
|
|
osal_wait_init(&g_avplay_instance[i].wq);
|
|
}
|
|
}
|
|
|
|
static avplay_drv_instance *drv_instance_get(td_handle handle)
|
|
{
|
|
td_ulong flags = 0;
|
|
avplay_drv_instance *instance = TD_NULL;
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
instance = instance_get(handle);
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
return instance;
|
|
}
|
|
|
|
static td_s32 drv_instance_alloc(td_handle *handle, const void *unique)
|
|
{
|
|
td_s32 ret;
|
|
td_ulong flags = 0;
|
|
avplay_drv_ctx *ctx = TD_NULL;
|
|
|
|
ctx = (avplay_drv_ctx*)avplay_malloc(sizeof(avplay_drv_ctx));
|
|
check_null(ctx);
|
|
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
ret = instance_alloc(handle, unique, &ctx);
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
if (ret != TD_SUCCESS || ctx != TD_NULL) {
|
|
avplay_free(ctx);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_instance_del(td_handle handle)
|
|
{
|
|
td_s32 ret;
|
|
td_ulong flags = 0;
|
|
avplay_drv_ctx *free_ctx = TD_NULL;
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
ret = instance_del(handle, &free_ctx);
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
if (free_ctx != TD_NULL) {
|
|
avplay_free(free_ctx);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_instance_clear(const void *unique)
|
|
{
|
|
td_s32 ret;
|
|
td_ulong flags = 0;
|
|
td_u32 i = 0;
|
|
avplay_drv_ctx *free_ctx[AVPLAY_MAX_CNT] = {TD_NULL};
|
|
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
ret = instance_clear(unique, free_ctx, AVPLAY_MAX_CNT);
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
if (free_ctx[i] != TD_NULL) {
|
|
avplay_free(free_ctx[i]);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static void drv_instance_deinit(void)
|
|
{
|
|
td_ulong flags = 0;
|
|
td_u32 i = 0;
|
|
avplay_drv_ctx *free_ctx[AVPLAY_MAX_CNT] = {TD_NULL};
|
|
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
instance_deinit(free_ctx, AVPLAY_MAX_CNT);
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
if (free_ctx[i] != TD_NULL) {
|
|
avplay_free(free_ctx[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define AVPLAY_INSTANCE (instance)
|
|
#define AVPLAY_DRV_CTX (AVPLAY_INSTANCE->ctx)
|
|
#define avplay_drv_do_func(avplay, func) do { \
|
|
td_s32 ret = TD_SUCCESS; \
|
|
td_ulong flags = 0; \
|
|
avplay_drv_instance *AVPLAY_INSTANCE = drv_instance_get(avplay); \
|
|
check_null(AVPLAY_INSTANCE); \
|
|
avplay_spin_lock(&AVPLAY_INSTANCE->spin, flags); \
|
|
\
|
|
if (AVPLAY_DRV_CTX != TD_NULL) { \
|
|
ret = func; \
|
|
} else { \
|
|
ret = SOC_ERR_AVPLAY_NULL_PTR; \
|
|
ext_err_avplay("Instance ctx is NULL\n"); \
|
|
} \
|
|
\
|
|
avplay_spin_unlock(&AVPLAY_INSTANCE->spin, flags); \
|
|
return ret; \
|
|
} while (0)
|
|
|
|
#define avplay_drv_do_func_without_spin(avplay, func) do { \
|
|
td_s32 ret = TD_SUCCESS; \
|
|
avplay_drv_instance *AVPLAY_INSTANCE = drv_instance_get(avplay); \
|
|
check_null(AVPLAY_INSTANCE); \
|
|
\
|
|
if (AVPLAY_DRV_CTX != TD_NULL) { \
|
|
ret = func; \
|
|
} else { \
|
|
ret = SOC_ERR_AVPLAY_NULL_PTR; \
|
|
ext_err_avplay("Instance ctx is NULL\n"); \
|
|
} \
|
|
\
|
|
return ret; \
|
|
} while (0)
|
|
|
|
static td_void set_resolution_param(const ext_vdec_size_change *vdec_param, avplay_resolution_param *param)
|
|
{
|
|
if (vdec_param == TD_NULL || param == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
param->width = vdec_param->new_width;
|
|
param->height = vdec_param->new_height;
|
|
param->stride = vdec_param->new_stride;
|
|
param->bit_depth = vdec_param->new_bit_depth;
|
|
param->frm_num = vdec_param->new_frm_num;
|
|
param->frm_size = vdec_param->new_frm_size;
|
|
param->meta_size = vdec_param->new_meta_size;
|
|
}
|
|
|
|
static td_s32 event_process(avplay_drv_instance *instance, avplay_event_type event, td_u64 param)
|
|
{
|
|
avplay_drv_ctx *ctx = instance->ctx;
|
|
|
|
check_null(ctx);
|
|
check_param(event < AVPLAY_EVENT_TYPE_MAX);
|
|
|
|
if (event == AVPLAY_EVENT_VID_DECODE_RESOLUTION_CHANGE) {
|
|
const ext_vdec_size_change *res = (ext_vdec_size_change *)(uintptr_t)param;
|
|
set_resolution_param(res, &ctx->res);
|
|
}
|
|
|
|
if (ctx->events[event].param_type == AVPLAY_PARAM_ADD) {
|
|
ctx->events[event].param += param;
|
|
} else if (ctx->events[event].param_type == AVPLAY_PARAM_RES) {
|
|
ctx->events[event].param = param;
|
|
} else {
|
|
ctx->events[event].param++;
|
|
}
|
|
|
|
ctx->events[event].update = TD_TRUE;
|
|
|
|
if (is_bit_enable(ctx->event_mask, event)) {
|
|
return drv_wakeup(instance);
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 process_callback_event(td_handle avplay, avplay_event_type event_type, td_u64 event_param)
|
|
{
|
|
td_s32 ret;
|
|
td_ulong flags = 0;
|
|
avplay_drv_instance *instance = TD_NULL;
|
|
instance = drv_instance_get(avplay);
|
|
if (instance == TD_NULL) {
|
|
ext_warn_avplay("Instance is not exist.\n");
|
|
return SOC_ERR_AVPLAY_NULL_PTR;
|
|
}
|
|
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
ret = event_process(instance, event_type, event_param);
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 vid_dmx_callback(td_handle avplay, ext_dmx_evt_id evt_id, const void *param, td_u32 param_size)
|
|
{
|
|
td_u64 event_param = 0LL;
|
|
avplay_event_type event_type = AVPLAY_EVENT_TYPE_MAX;
|
|
|
|
switch (evt_id) {
|
|
case EXT_DMX_EVT_ERR:
|
|
event_type = AVPLAY_EVENT_VID_DMX_ERR;
|
|
break;
|
|
case EXT_DMX_EVT_NEW_PES:
|
|
event_type = AVPLAY_EVENT_VID_NEW_PES;
|
|
break;
|
|
case EXT_DMX_EVT_EOS:
|
|
event_type = AVPLAY_EVENT_VID_DMX_EOS;
|
|
break;
|
|
case EXT_DMX_EVT_OVFL:
|
|
ext_warn_avplay("video demux event id[0x%x].\n", evt_id);
|
|
return TD_SUCCESS;
|
|
default:
|
|
ext_err_avplay("Unsupport video demux event id[0x%x].\n", evt_id);
|
|
return SOC_ERR_AVPLAY_NOT_SUPPORT;
|
|
}
|
|
|
|
soc_trace_avplay("Receive video demux event id[0x%x], avplay event id = 0x%x\n", evt_id, event_type);
|
|
|
|
return process_callback_event(avplay, event_type, event_param);
|
|
}
|
|
|
|
static td_s32 aud_dmx_callback(td_handle avplay, ext_dmx_evt_id evt_id, const void *param, td_u32 param_size)
|
|
{
|
|
td_u64 event_param = 0LL;
|
|
avplay_event_type event_type = AVPLAY_EVENT_TYPE_MAX;
|
|
|
|
switch (evt_id) {
|
|
case EXT_DMX_EVT_ERR:
|
|
event_type = AVPLAY_EVENT_AUD_DMX_ERR;
|
|
break;
|
|
case EXT_DMX_EVT_NEW_PES:
|
|
event_type = AVPLAY_EVENT_AUD_NEW_PES;
|
|
break;
|
|
case EXT_DMX_EVT_EOS:
|
|
event_type = AVPLAY_EVENT_AUD_DMX_EOS;
|
|
break;
|
|
case EXT_DMX_EVT_OVFL:
|
|
ext_warn_avplay("audio demux event id[0x%x].\n", evt_id);
|
|
return TD_SUCCESS;
|
|
default:
|
|
ext_err_avplay("Unsupport audio demux event id[0x%x].\n", evt_id);
|
|
return SOC_ERR_AVPLAY_NOT_SUPPORT;
|
|
}
|
|
|
|
soc_trace_avplay("Receive audio demux event id[0x%x], avplay event id = 0x%x\n", evt_id, event_type);
|
|
|
|
return process_callback_event(avplay, event_type, event_param);
|
|
}
|
|
|
|
static td_s32 pcr_dmx_callback(td_handle avplay, ext_dmx_evt_id evt_id, const void *param, td_u32 param_size)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
const dmx_sync_pcr *info = TD_NULL;
|
|
|
|
check_null(param);
|
|
|
|
if (evt_id == EXT_DMX_EVT_PCR) {
|
|
info = (const dmx_sync_pcr *)param;
|
|
ret = ext_drv_sync_pcr_proc(info->handle, info->pcr_value, info->scr_value);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 dmx_index_callback(td_handle avplay, ext_dmx_opt_type opt_type, const dmx_index_data *data)
|
|
{
|
|
check_null(data);
|
|
|
|
if (opt_type != EXT_DMX_OPT_ADD) {
|
|
return TD_SUCCESS;
|
|
} else if (data->frame_type != DMX_FRAME_TYPE_I && data->frame_type != DMX_FRAME_TYPE_IDR) {
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
ext_dbg_avplay("Receive demux index event: type[%d] size[%u] offset[%llu] pts[%lld] \n",
|
|
data->frame_type, data->frame_size, data->global_offset, data->pts_us);
|
|
|
|
return process_callback_event(avplay, AVPLAY_EVENT_VID_NEW_DMX_IDX, data->global_offset);
|
|
}
|
|
|
|
static void err_frame_info_to_u64(const void *param, td_u32 param_size, td_u64 *event_param)
|
|
{
|
|
const ext_vdec_err_frm *err_frame = (const ext_vdec_err_frm*)param;
|
|
td_u64 a = err_frame->err_frm_type;
|
|
td_u64 b = err_frame->err_ratio;
|
|
*event_param = big_endian_write(a, b);
|
|
}
|
|
|
|
static td_s32 vdec_evt_map_with_param(ext_vdec_evt_id evt_id, const void *param, td_u32 param_size,
|
|
avplay_event_type *avplay_evt, td_u64 *event_param)
|
|
{
|
|
check_null(param);
|
|
|
|
switch (evt_id) {
|
|
case EXT_VDEC_EVT_FIRST_PTS: {
|
|
*avplay_evt = AVPLAY_EVENT_VID_FIRST_PTS;
|
|
*event_param = *(const td_s64*)param;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_SECOND_PTS: {
|
|
*avplay_evt = AVPLAY_EVENT_VID_SECOND_PTS;
|
|
*event_param = *(const td_s64*)param;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_EOS: {
|
|
const ext_vdec_eos_param *eos = param;
|
|
*avplay_evt = AVPLAY_EVENT_VID_DECODE_EOS;
|
|
*event_param = eos->last_frame_flag;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_ERR_STANDARD: {
|
|
*avplay_evt = AVPLAY_EVENT_VID_TYPE_ERR;
|
|
*event_param = *(const td_u32*)param;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_NORM_CHG: {
|
|
const ext_vdec_norm_param *norm = param;
|
|
*avplay_evt = AVPLAY_EVENT_VID_DECODE_FORMAT_CHANGE;
|
|
*event_param = norm->norm_type;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_SIZE_CHG: {
|
|
const ext_vdec_size_change *res = param;
|
|
*avplay_evt = AVPLAY_EVENT_VID_DECODE_RESOLUTION_CHANGE;
|
|
*event_param = (td_u64)(uintptr_t)res;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_FRM_PCK_CHG: {
|
|
*avplay_evt = AVPLAY_EVENT_VID_DECODE_PACKING_CHANGE;
|
|
*event_param = *(const td_u32*)param;
|
|
break;
|
|
}
|
|
case EXT_VDEC_EVT_ERR_FRAME: {
|
|
*avplay_evt = AVPLAY_EVENT_VID_ERR_FRAME;
|
|
err_frame_info_to_u64(param, param_size, event_param);
|
|
break;
|
|
}
|
|
default:
|
|
ext_err_avplay("Unsupport vdec event id[0x%x]\n", evt_id);
|
|
return SOC_ERR_AVPLAY_NOT_SUPPORT;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 vdec_callback(td_handle avplay, ext_vdec_evt_id evt_id, const void *param, td_u32 param_size)
|
|
{
|
|
td_s32 ret;
|
|
td_u64 event_param = 0LL;
|
|
avplay_event_type event_type = AVPLAY_EVENT_TYPE_MAX;
|
|
|
|
switch (evt_id) {
|
|
case EXT_VDEC_EVT_NEW_FRAME:
|
|
event_type = AVPLAY_EVENT_VID_NEW_FRAME;
|
|
break;
|
|
case EXT_VDEC_EVT_NEW_STREAM:
|
|
event_type = AVPLAY_EVENT_VID_RLS_PES;
|
|
break;
|
|
case EXT_VDEC_EVT_NEW_USER_DATA:
|
|
event_type = AVPLAY_EVENT_VID_NEW_USER_DATA;
|
|
break;
|
|
case EXT_VDEC_EVT_UNSUPPORT:
|
|
event_type = AVPLAY_EVENT_VID_UNSUPPORT;
|
|
break;
|
|
default:
|
|
ret = vdec_evt_map_with_param(evt_id, param, param_size, &event_type, &event_param);
|
|
return_when_error(ret, vdec_evt_map_with_param);
|
|
}
|
|
|
|
soc_trace_avplay("Receive vdec event id[0x%x], avplay event id = 0x%x\n", evt_id, event_type);
|
|
|
|
return process_callback_event(avplay, event_type, event_param);
|
|
}
|
|
|
|
static td_bool pop_event(avplay_drv_ctx *ctx, avplay_event_type *event, td_u64 *param)
|
|
{
|
|
td_s32 i;
|
|
avplay_event_info *event_info = TD_NULL;
|
|
if (ctx == TD_NULL) {
|
|
return TD_FALSE;
|
|
}
|
|
|
|
for (i = 0; i < AVPLAY_EVENT_TYPE_MAX; i++) {
|
|
event_info = &ctx->events[i];
|
|
if (event_info->update) {
|
|
*event = i;
|
|
*param = event_info->param;
|
|
|
|
event_info->update = TD_FALSE;
|
|
event_info->param = 0LL;
|
|
return TD_TRUE;
|
|
}
|
|
}
|
|
|
|
return TD_FALSE;
|
|
}
|
|
|
|
static td_bool drv_pop_event(avplay_drv_instance *instance, avplay_event_type *event, td_u64 *param)
|
|
{
|
|
td_bool ret;
|
|
td_ulong flags = 0;
|
|
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
ret = pop_event(instance->ctx, event, param);
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_reset(avplay_drv_ctx *ctx, avplay_channel_type chn)
|
|
{
|
|
td_u32 i;
|
|
(void)chn;
|
|
|
|
for (i = 0; i < AVPLAY_EVENT_TYPE_MAX; i++) {
|
|
ctx->events[i].update = TD_FALSE;
|
|
ctx->events[i].param = 0LL;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_set_channel_state(avplay_drv_ctx *ctx, avplay_channel_type chn, avplay_channel_state state)
|
|
{
|
|
if (chn == AVPLAY_CHANNEL_AUD || chn == AVPLAY_CHANNEL_MAX) {
|
|
if (state == AVPLAY_CHANNEL_START) {
|
|
ctx->aud_enable = TD_TRUE;
|
|
} else if (state == AVPLAY_CHANNEL_STOP) {
|
|
ctx->aud_enable = TD_FALSE;
|
|
}
|
|
}
|
|
|
|
if (chn == AVPLAY_CHANNEL_VID || chn == AVPLAY_CHANNEL_MAX) {
|
|
if (state == AVPLAY_CHANNEL_START) {
|
|
ctx->vid_enable = TD_TRUE;
|
|
} else if (state == AVPLAY_CHANNEL_STOP) {
|
|
ctx->vid_enable = TD_FALSE;
|
|
}
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static void drv_set_dmx_index_callback(td_handle dmx, avplay_drv_instance *instance,
|
|
drv_dmx_play_index_callback callback)
|
|
{
|
|
td_s32 ret;
|
|
td_handle avplay;
|
|
td_ulong flags = 0;
|
|
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx == TD_NULL) {
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
return;
|
|
}
|
|
avplay = instance->ctx->self;
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
if (dmx == TD_INVALID_HANDLE ||
|
|
g_avplay_import_func.dmx_func == TD_NULL ||
|
|
g_avplay_import_func.dmx_func->dmx_set_play_index_callback == TD_NULL) {
|
|
ext_err_avplay("dmx_set_play_index_callback is NULL, cannot set callback\n");
|
|
return;
|
|
}
|
|
|
|
ret = g_avplay_import_func.dmx_func->dmx_set_play_index_callback(dmx, avplay, callback);
|
|
log_when_error(ret, dmx_set_play_index_callback);
|
|
|
|
return;
|
|
}
|
|
|
|
static td_s32 drv_set_dmx_callback(avplay_drv_instance *instance, td_handle handle,
|
|
avplay_resource_type type, drv_dmx_callback callback)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
td_handle avplay;
|
|
td_handle dmx_handle = TD_INVALID_HANDLE;
|
|
td_ulong flags = 0;
|
|
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx == TD_NULL) {
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
avplay = instance->ctx->self;
|
|
switch (type) {
|
|
case AVPLAY_RESOURCE_TYPE_VID_DEMUX: {
|
|
dmx_handle = instance->ctx->vid_dmx;
|
|
instance->ctx->vid_dmx = handle;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_AUD_DEMUX: {
|
|
dmx_handle = instance->ctx->aud_dmx;
|
|
instance->ctx->aud_dmx = handle;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_PCR_DEMUX: {
|
|
dmx_handle = instance->ctx->pcr_dmx;
|
|
instance->ctx->pcr_dmx = handle;
|
|
break;
|
|
}
|
|
default: {
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
return TD_FAILURE;
|
|
}
|
|
}
|
|
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
if (g_avplay_import_func.dmx_func == TD_NULL ||
|
|
g_avplay_import_func.dmx_func->dmx_set_callback == TD_NULL) {
|
|
ext_err_avplay("drv_dmx_set_callback is NULL, cannot set resrouce\n");
|
|
return SOC_ERR_AVPLAY_INVALID_OPT;
|
|
}
|
|
|
|
if (handle != TD_INVALID_HANDLE) {
|
|
ret = g_avplay_import_func.dmx_func->dmx_set_callback(handle, avplay, callback);
|
|
} else if (dmx_handle != TD_INVALID_HANDLE) {
|
|
ret = g_avplay_import_func.dmx_func->dmx_set_callback(dmx_handle, avplay, TD_NULL);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_set_vdec_callback(avplay_drv_instance *instance, td_handle handle,
|
|
fn_drv_vdec_callback callback)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
td_ulong flags = 0;
|
|
td_handle avplay;
|
|
td_handle vdec_handle;
|
|
fn_drv_vdec_set_callback vdec_set_cb = TD_NULL;
|
|
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx == TD_NULL) {
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
avplay = instance->ctx->self;
|
|
vdec_handle = instance->ctx->vdec;
|
|
instance->ctx->vdec = handle;
|
|
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
if (g_avplay_import_func.vdec_func != TD_NULL &&
|
|
g_avplay_import_func.vdec_func->pfn_drv_vdec_set_callback != TD_NULL) {
|
|
vdec_set_cb = g_avplay_import_func.vdec_func->pfn_drv_vdec_set_callback;
|
|
} else {
|
|
ext_err_avplay("drv_vdec_set_callback is NULL, cannot set resrouce\n");
|
|
return SOC_ERR_AVPLAY_INVALID_OPT;
|
|
}
|
|
|
|
if (handle != TD_INVALID_HANDLE) {
|
|
ret = vdec_set_cb(handle, avplay, vdec_callback);
|
|
} else if (vdec_handle != TD_INVALID_HANDLE) {
|
|
ret = vdec_set_cb(vdec_handle, avplay, TD_NULL);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_bool find_virtual_win(const avplay_drv_instance *instance, td_handle handle, td_u32 *index)
|
|
{
|
|
td_u32 i;
|
|
for (i = 0; i < DRV_AVPLAY_MAX_VIR_WIN_CNT; i++) {
|
|
if (instance->ctx->virtual_win[i] == handle) {
|
|
*index = i;
|
|
return TD_TRUE;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < DRV_AVPLAY_MAX_VIR_WIN_CNT; i++) {
|
|
if (instance->ctx->virtual_win[i] == TD_INVALID_HANDLE) {
|
|
*index = i;
|
|
return TD_FALSE;
|
|
}
|
|
}
|
|
|
|
return TD_FALSE;
|
|
}
|
|
|
|
static td_s32 set_win_resource(avplay_drv_instance *instance, td_handle handle, td_u32 param)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
td_ulong flags = 0;
|
|
td_u32 index = 0;
|
|
td_bool is_win_valid;
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx == TD_NULL) {
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
if (param == TD_FALSE) {
|
|
if (instance->ctx->win == TD_INVALID_HANDLE) {
|
|
ext_dbg_avplay("attach master window[0x%x] to avplay[0x%x]\n", handle, instance->ctx->self);
|
|
instance->ctx->win = handle;
|
|
} else if (instance->ctx->win == handle) {
|
|
ext_dbg_avplay("detach master window[0x%x] to avplay[0x%x]\n", handle, instance->ctx->self);
|
|
instance->ctx->win = TD_INVALID_HANDLE;
|
|
} else {
|
|
ext_err_avplay("Only one master window is suppurted\n");
|
|
ret = TD_FAILURE;
|
|
}
|
|
} else {
|
|
is_win_valid = find_virtual_win(instance, handle, &index);
|
|
if (is_win_valid == TD_TRUE) {
|
|
ext_dbg_avplay("detach virtual window[0x%x] to avplay[0x%x]\n", handle, instance->ctx->self);
|
|
instance->ctx->virtual_win[index] = TD_INVALID_HANDLE;
|
|
instance->ctx->virtual_win_cnt--;
|
|
} else if (index < DRV_AVPLAY_MAX_VIR_WIN_CNT) {
|
|
ext_dbg_avplay("attach virturl window[0x%x] to avplay[0x%x]\n", handle, instance->ctx->self);
|
|
instance->ctx->virtual_win[index] = handle;
|
|
instance->ctx->virtual_win_cnt++;
|
|
} else {
|
|
ext_err_avplay("Too many windwos[%zu] attached\n", instance->ctx->virtual_win_cnt);
|
|
ret = TD_FAILURE;
|
|
}
|
|
}
|
|
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_set_resource(avplay_drv_instance *instance, td_handle handle, avplay_resource_type type, td_u32 param)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
td_ulong flags = 0;
|
|
|
|
switch (type) {
|
|
case AVPLAY_RESOURCE_TYPE_VID_DEMUX: {
|
|
ret = drv_set_dmx_callback(instance, handle, type, vid_dmx_callback);
|
|
drv_set_dmx_index_callback(handle, instance, dmx_index_callback);
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_AUD_DEMUX: {
|
|
ret = drv_set_dmx_callback(instance, handle, type, aud_dmx_callback);
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_PCR_DEMUX: {
|
|
ret = drv_set_dmx_callback(instance, handle, type, pcr_dmx_callback);
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_VDEC: {
|
|
ret = drv_set_vdec_callback(instance, handle, vdec_callback);
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_WINDOW: {
|
|
ret = set_win_resource(instance, handle, param);
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_SYNC: {
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx != TD_NULL) {
|
|
instance->ctx->sync = handle;
|
|
}
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
break;
|
|
}
|
|
default: {
|
|
ext_err_avplay("Unsupport resource type[%d]\n", type);
|
|
ret = SOC_ERR_AVPLAY_NOT_SUPPORT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return_when_error(ret, set_resource);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_get_avplay_handle_by_window(td_handle win, td_handle *avplay)
|
|
{
|
|
td_u32 i = 0;
|
|
td_ulong flags = 0;
|
|
*avplay = TD_INVALID_HANDLE;
|
|
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
for (; i < AVPLAY_MAX_CNT; i++) {
|
|
if (g_avplay_instance[i].ctx != TD_NULL && g_avplay_instance[i].ctx->win == win) {
|
|
*avplay = g_avplay_instance[i].ctx->self;
|
|
break;
|
|
}
|
|
}
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
return (*avplay == TD_INVALID_HANDLE) ? SOC_ERR_AVPLAY_NO_DATA : TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_get_resource(const avplay_drv_ctx *ctx, avplay_resource_type type, td_u32 param, td_handle *dst)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
|
|
*dst = TD_INVALID_HANDLE;
|
|
switch (type) {
|
|
case AVPLAY_RESOURCE_TYPE_VID_DEMUX: {
|
|
*dst = ctx->vid_dmx;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_AUD_DEMUX: {
|
|
*dst = ctx->aud_dmx;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_PCR_DEMUX: {
|
|
*dst = ctx->pcr_dmx;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_VDEC: {
|
|
*dst = ctx->vdec;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_WINDOW: {
|
|
*dst = ctx->win;
|
|
break;
|
|
}
|
|
case AVPLAY_RESOURCE_TYPE_SYNC: {
|
|
*dst = ctx->sync;
|
|
break;
|
|
}
|
|
default: {
|
|
ext_err_avplay("Unsupport resource type[%d]\n", type);
|
|
ret = SOC_ERR_AVPLAY_NOT_SUPPORT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return_when_error(ret, get_resource);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_get_global_play_info(const avplay_drv_ctx *ctx, avplay_global_play_info *info)
|
|
{
|
|
info->audio_enable = ctx->aud_enable;
|
|
info->video_enable = ctx->vid_enable;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_wakeup(avplay_drv_instance *instance)
|
|
{
|
|
instance->wait_cond = TD_TRUE;
|
|
osal_wait_wakeup(&instance->wq);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static int drv_wait_cond(const void *param)
|
|
{
|
|
if (*(const td_bool*)param) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static td_s32 drv_wait_event(avplay_drv_instance *instance, td_u64 event_mask,
|
|
avplay_event_type *event, td_u64 *param, td_s64 timeout)
|
|
{
|
|
td_s32 ret = TD_FAILURE;
|
|
td_ulong flags = 0;
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
if (instance->ctx != TD_NULL) {
|
|
instance->ctx->event_mask = event_mask;
|
|
}
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
*event = AVPLAY_EVENT_TYPE_MAX;
|
|
if (!drv_pop_event(instance, event, param)) {
|
|
avplay_mutex_unlock(&instance->mutex);
|
|
ret = osal_wait_timeout_interruptible(&instance->wq, drv_wait_cond, &instance->wait_cond, (td_ulong)timeout);
|
|
avplay_mutex_lock(&instance->mutex);
|
|
|
|
(void)drv_pop_event(instance, event, param);
|
|
instance->wait_cond = TD_FALSE;
|
|
}
|
|
|
|
if (*event != AVPLAY_EVENT_TYPE_MAX) {
|
|
ret = TD_SUCCESS;
|
|
} else if (ret == 0) {
|
|
ret = SOC_ERR_AVPLAY_TIMEOUT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_get_video_info(avplay_drv_instance *instance, avplay_video_info *info)
|
|
{
|
|
td_s32 ret;
|
|
ext_vdec_feature feature = {0};
|
|
fn_drv_vdec_get_param vdec_get_param = TD_NULL;
|
|
td_handle vdec;
|
|
td_ulong flags = 0;
|
|
|
|
if (instance == TD_NULL || instance->ctx == TD_NULL) {
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
avplay_spin_lock(&instance->spin, flags);
|
|
vdec = instance->ctx->vdec;
|
|
avplay_spin_unlock(&instance->spin, flags);
|
|
|
|
if (g_avplay_import_func.vdec_func != TD_NULL &&
|
|
g_avplay_import_func.vdec_func->pfn_drv_vdec_get_param != TD_NULL) {
|
|
vdec_get_param = g_avplay_import_func.vdec_func->pfn_drv_vdec_get_param;
|
|
}
|
|
|
|
if (vdec_get_param == TD_NULL || vdec == TD_INVALID_HANDLE) {
|
|
return TD_SUCCESS; /* return success if vdec not exist */
|
|
}
|
|
|
|
ret = vdec_get_param(vdec, EXT_VDEC_PARAM_FEATURE, &feature, sizeof(ext_vdec_feature));
|
|
if (ret != TD_SUCCESS) {
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
info->width = feature.dec_width;
|
|
info->height = feature.dec_height;
|
|
info->aspect_width = feature.aspect_width;
|
|
info->aspect_height = feature.aspect_height;
|
|
info->fps = feature.frame_rate;
|
|
info->sampling_type = feature.sampling_type;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_get_event_param(const avplay_drv_instance *instance, avplay_event_param *param)
|
|
{
|
|
const avplay_drv_ctx *ctx = instance->ctx;
|
|
|
|
param->res_param.width = ctx->res.width;
|
|
param->res_param.height = ctx->res.height;
|
|
param->res_param.stride = ctx->res.stride;
|
|
param->res_param.bit_depth = ctx->res.bit_depth;
|
|
param->res_param.frm_num = ctx->res.frm_num;
|
|
param->res_param.frm_size = ctx->res.frm_size;
|
|
param->res_param.meta_size = ctx->res.meta_size;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_avplay_import_function(void)
|
|
{
|
|
td_s32 ret;
|
|
td_ulong flags = 0;
|
|
demux_func_export *dmx_func = TD_NULL;
|
|
drv_vdec_export_func *vdec_func = TD_NULL;
|
|
|
|
ret = ext_drv_module_get_func(SOC_ID_DEMUX, (void **)&dmx_func);
|
|
log_when_error(ret, ext_drv_module_get_func);
|
|
|
|
ret = ext_drv_module_get_func(SOC_ID_VDEC, (void **)&vdec_func);
|
|
log_when_error(ret, ext_drv_module_get_func);
|
|
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
|
|
g_avplay_import_func.dmx_func = dmx_func;
|
|
g_avplay_import_func.vdec_func = vdec_func;
|
|
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_avplay_set_channel_state(td_handle avplay, avplay_channel_type chn, avplay_channel_state state)
|
|
{
|
|
avplay_drv_do_func(avplay, drv_set_channel_state(AVPLAY_DRV_CTX, chn, state));
|
|
}
|
|
|
|
static td_s32 drv_avplay_get_resource(td_handle avplay, avplay_resource_type type, td_u32 param, td_handle *dst)
|
|
{
|
|
avplay_drv_do_func(avplay, drv_get_resource(AVPLAY_DRV_CTX, type, param, dst));
|
|
}
|
|
|
|
static td_s32 drv_avplay_get_global_play_info(td_handle avplay, avplay_global_play_info *info)
|
|
{
|
|
avplay_drv_do_func(avplay, drv_get_global_play_info(AVPLAY_DRV_CTX, info));
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_create(td_handle *avplay, const void *unique)
|
|
{
|
|
check_null(avplay);
|
|
return drv_instance_alloc(avplay, unique);
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_destroy(td_handle avplay)
|
|
{
|
|
return drv_instance_del(avplay);
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_reset(td_handle avplay, avplay_channel_type chn)
|
|
{
|
|
avplay_drv_do_func(avplay, drv_reset(AVPLAY_DRV_CTX, chn));
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_set_channel_state(td_handle avplay, avplay_channel_type chn, avplay_channel_state state)
|
|
{
|
|
td_ulong flags = 0;
|
|
avplay_spin_lock(&g_avplay_spinlock, flags);
|
|
|
|
if (state == AVPLAY_CHANNEL_START) {
|
|
g_avplay_play_cnt++;
|
|
}
|
|
|
|
avplay_spin_unlock(&g_avplay_spinlock, flags);
|
|
|
|
return drv_avplay_set_channel_state(avplay, chn, state);
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_set_resource(td_handle avplay, td_handle handle, avplay_resource_type type, td_u32 param)
|
|
{
|
|
avplay_drv_do_func_without_spin(avplay, drv_set_resource(AVPLAY_INSTANCE, handle, type, param));
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_get_resource(td_handle src, avplay_resource_type type, td_u32 param, td_handle *dst)
|
|
{
|
|
check_null(dst);
|
|
|
|
if (type == AVPLAY_RESOURCE_TYPE_AVPLAY) {
|
|
return drv_get_avplay_handle_by_window(src, dst);
|
|
} else {
|
|
return drv_avplay_get_resource(src, type, param, dst);
|
|
}
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_wakeup(td_handle avplay)
|
|
{
|
|
avplay_drv_do_func_without_spin(avplay, drv_wakeup(AVPLAY_INSTANCE));
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_wait_event(td_handle avplay, td_u64 event_mask,
|
|
avplay_event_type *event, td_u64 *param, td_s64 timeout)
|
|
{
|
|
check_null(event);
|
|
check_null(param);
|
|
|
|
avplay_drv_do_func_without_spin(avplay, drv_wait_event(AVPLAY_INSTANCE, event_mask, event, param, timeout));
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_get_video_info(td_handle avplay, avplay_video_info *info)
|
|
{
|
|
check_null(info);
|
|
|
|
avplay_drv_do_func_without_spin(avplay, drv_get_video_info(AVPLAY_INSTANCE, info));
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_get_global_play_info(td_handle avplay, avplay_global_play_info *info)
|
|
{
|
|
check_null(info);
|
|
|
|
info->content_count = g_avplay_play_cnt;
|
|
return drv_avplay_get_global_play_info(avplay, info);
|
|
}
|
|
|
|
td_s32 ext_drv_avplay_get_event_param(td_handle avplay, avplay_event_param *param)
|
|
{
|
|
check_null(param);
|
|
|
|
avplay_drv_do_func(avplay, drv_get_event_param(AVPLAY_INSTANCE, param));
|
|
}
|
|
|
|
td_s32 avplay_init(void)
|
|
{
|
|
avplay_spin_init(&g_avplay_spinlock);
|
|
drv_instance_init();
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 avplay_deinit(void)
|
|
{
|
|
drv_instance_deinit();
|
|
avplay_spin_deinit(&g_avplay_spinlock);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 avplay_open(void *private_data)
|
|
{
|
|
return drv_avplay_import_function();
|
|
}
|
|
|
|
td_s32 avplay_release(void *private_data)
|
|
{
|
|
return drv_instance_clear(private_data);
|
|
}
|
|
|