/** * \page Test * \section Introduction * test code with CAS Hal APIs. * It supports: * \li Live * \li Record * \li Playback * \li Timeshift * * \section Usage * * Help msg will be shown if the test runs without parameters.\n * There are some general concepts for the parameters: * * For Live: * \code * cas_hal_test live * \endcode * For Live local: * \code * cas_hal_test local * \endcode * For playback: * \code * cas_hal_test dvrplay * \endcode * the timeshift backgroud recording file will be located in /data/data as: * \code * /data/data/timeshifting-xxxx.* * \endcode * * \section FormatCode Format Code * * \li quit\n * quit the test */ #ifndef CA_DEBUG_LEVEL #define CA_DEBUG_LEVEL 2 #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ANDROID #include #endif #include "AmTsPlayer.h" #include "dvr_segment.h" #include "dvr_wrapper.h" #include "dvb_utils.h" #include "fend.h" #ifdef UNUSED #undef UNUSED #endif #include "am_cas.h" #include "cas_json.h" #include "scan.h" #define INF(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) #define ERR(fmt, ...) fprintf(stderr, "error:" fmt, ##__VA_ARGS__) #define FEND_DEV_NO (0) #define DMX_DEV_NO (0) #define DMX_DEV_NO_2ND (1) #define AV_DEV_NO (0) #define DSC_DEV_NO (0) #define DVR_DEV_NO (0) /* Don't think about pip/fcc. two worst cases in record: #1, live + double record: live 0, record 1, record 2 #2, timeshift + record: timeshift record use 0, timeshift playback use 1, another record use 2 For tse record: 0 and 1, tse_dmx_dev_id use dev 4, fta_dmx_dev_id use dev 5. 2 tse_dmx_dev_id use dev 6, fta_dmx_dev_id use dev 7. */ #define MAX_REC_NUM (4) #define VMX_CAS_STRING "Verimatrix" #define NAGRA_CAS_STRING "Nagra" #define X2_INJECT_LENGTH (256*1024) #define X2_BLOCK_SIZE (256*1024) #define X4_INJECT_LENGTH (188*1024) #define X4_BLOCK_SIZE (188*1024)//same to asyncfifo flush size, it's enc block size and dec block size//65424 #define DVR_STREAM_TYPE_TO_TYPE(_t) (((_t) >> 24) & 0xF) #define DVR_STREAM_TYPE_TO_FMT(_t) ((_t) & 0x8F) #define has_live(_m_) ((_m_) & LIVE) #define has_live_local(_m_) ((_m_) & LIVE_LOCAL) #define has_playback(_m_) ((_m_) & PLAYBACK) #define has_recording(_m_) ((_m_) & RECORDING) #define is_live(_m_) ((_m_) == LIVE) #define is_live_local(_m_) ((_m_) == LIVE_LOCAL) #define is_playback(_m_) ((_m_) == PLAYBACK) #define is_timeshifting(_m_) ((_m_) == TIMESHIFTING) #define is_ext_playback(_m_) ((_m_) == EXT_PLAYBACK) struct vm_config_t { uint8_t run; uint8_t on; uint8_t config; uint8_t strength; } g_vm_config = {0}; struct oc_config_t { uint8_t run; uint32_t flag; uint8_t analog; uint8_t cgmsa; uint8_t emicci; } g_oc_config = {0}; typedef struct { CasSession cas_session; SecMemHandle secmem_session; void *dvr_session; //'DVR_WrapperPlayback_t *' or 'DVR_WrapperRecord_t *' am_tsplayer_handle player_session; int replayed; } CasTestSession; typedef enum { PIN_NEED_CHECK, PIN_CHECK_SUCCESS, PIN_CHECK_FAILED, PIN_MAX, } PIN_STATUS; static int mode = 0; static int duration=180000; static int size=1024*1024*1024; static char *pfilename = "/data/data/timeshifting.ts"; static int check_pin_status = PIN_MAX; static int rec_status = 0; static int32_t seclev = AM_TSPLAYER_DMX_FILTER_SEC_LEVEL2; static uint32_t video_tunnel_id = 0; static uint32_t inject_length = X4_INJECT_LENGTH; static uint32_t block_size = X4_BLOCK_SIZE; static const char* IOCTRL_INVOKE_GET_CAS_MODE = "{\"InvokeID\":3}"; int g_nosmp = 0; int g_indexer = 0; int g_tse_key_mode [MAX_REC_NUM]= {-1, -1, -1, -1}; //add for x4 #define TSN_PATH "/sys/class/stb/tsn_source" #define TSN_IPTV "local" #define TSN_DVB "demod" #define VIDEO_AXIS_PATH "/sys/class/video/axis" enum { LIVE = 0x01, LIVE_LOCAL = 0x02, PLAYBACK = 0x04, RECORDING = 0x08, TIMESHIFTING = PLAYBACK | RECORDING | 0x10, EXT_PLAYBACK = PLAYBACK | 0x10, }; static CasHandle g_cas_handle = 0; static CasTestSession play; static CasTestSession recorder[MAX_REC_NUM]; static pthread_t gInjectThread; static pthread_t gScbUpdateThread[MAX_REC_NUM]; static int running = 1; static int gInjectRunning = 0; static int g_frontend_id = -1; static int watermark_test_config( uint8_t on, uint8_t config, uint8_t strength); static int output_control_test_config( uint32_t flag, uint8_t analog, uint8_t cgmsa, uint8_t emicci); static bool get_cas_mode(CasSession session); static int get_tse_key_mode(CasSession session); static AM_RESULT cas_event_cb(CasSession session, char *json); static void video_callback(void *user_data, am_tsplayer_event *event); extern int ext_dvr_playback_stop(void); extern int ext_dvr_playback(const char *path, CasHandle cas_handle); extern int dvr_wrapper_set_playback_secure_buffer (DVR_WrapperPlayback_t playback, uint8_t *p_secure_buf, uint32_t len); int amsysfs_set_sysfs_str(const char *path, const char *val); //convert am video codec fmt to dvb fmt bool convert_video_codec_fmt_am2dvb(am_tsplayer_video_codec am_fmt, DVR_VideoFormat_t* dvb_fmt) { if (!dvb_fmt) return false; bool result = true; switch (am_fmt) { case AV_VIDEO_CODEC_MPEG1: *dvb_fmt = DVR_VIDEO_FORMAT_MPEG1; break; case AV_VIDEO_CODEC_MPEG2: *dvb_fmt = DVR_VIDEO_FORMAT_MPEG2; break; case AV_VIDEO_CODEC_H265: *dvb_fmt = DVR_VIDEO_FORMAT_HEVC; break; case AV_VIDEO_CODEC_H264: *dvb_fmt = DVR_VIDEO_FORMAT_H264; break; case AV_VIDEO_CODEC_VP9: *dvb_fmt = DVR_VIDEO_FORMAT_VP9; break; default: ERR("Not supported type convert, am_tsplayer_video_codec:%d\n", am_fmt); result = false; break; } return result; } //convert am audio codec fmt to dvb fmt bool convert_audio_codec_fmt_am2dvb(am_tsplayer_audio_codec am_fmt, DVR_AudioFormat_t* dvb_fmt) { if (!dvb_fmt) return false; bool result = true; switch (am_fmt) { case AV_AUDIO_CODEC_MP2: *dvb_fmt = DVR_AUDIO_FORMAT_MPEG; break; case AV_AUDIO_CODEC_MP3: *dvb_fmt = DVR_AUDIO_FORMAT_MPEG; break; case AV_AUDIO_CODEC_AC3: *dvb_fmt = DVR_AUDIO_FORMAT_AC3; break; case AV_AUDIO_CODEC_EAC3: *dvb_fmt = DVR_AUDIO_FORMAT_EAC3; break; case AV_AUDIO_CODEC_DTS: *dvb_fmt = DVR_AUDIO_FORMAT_DTS; break; case AV_AUDIO_CODEC_AAC: *dvb_fmt = DVR_AUDIO_FORMAT_AAC; break; case AV_AUDIO_CODEC_LATM: *dvb_fmt = DVR_AUDIO_FORMAT_LATM; break; case AV_AUDIO_CODEC_PCM: *dvb_fmt = DVR_AUDIO_FORMAT_PCM; break; case AV_AUDIO_CODEC_AC4: *dvb_fmt = DVR_AUDIO_FORMAT_AC4; break; default: ERR("Not supported type convert, am_tsplayer_audio_codec:%d\n", am_fmt); result = false; break; } return result; } static int fend_lock(int dev_no, int freqM, int sym) { int ret; int fend_id = -1; int wait_time = 3; dmd_delivery_t delivery; dmd_tuner_event_t status = TUNER_STATE_UNKNOWN; if (open_fend(dev_no, &fend_id)) { ERR("fend open failed\n"); return -1; } memset(&delivery, 0, sizeof(delivery)); delivery.device_type = DMD_CABLE; delivery.delivery.cable.frequency = freqM*1000; delivery.delivery.cable.symbol_rate = sym; delivery.delivery.cable.modulation = DMD_MOD_QAM;//DMD_MOD_128QAM; ret = dmd_lock_c(fend_id, &delivery); INF("DVB-C: lock to freq:%d, modulation:%d symbol_rate:%d ret:%d \n", delivery.delivery.cable.frequency, delivery.delivery.cable.modulation, delivery.delivery.cable.symbol_rate, ret); if (ret) { ERR("lock failed, ret:%d\n", ret); close_fend(fend_id); return -1; } g_frontend_id = fend_id; while (wait_time--) { sleep(1); status = get_dmd_lock_status(fend_id); if (status == TUNER_STATE_LOCKED) break; } if (status == TUNER_STATE_LOCKED) { return 0; } else { ERR("Try 3 times but lock failed, status:%d\n", status); close_fend(fend_id); return -1; } } int init_tsplayer_inject(dvb_service_info_t *prog) { int ret; am_tsplayer_handle session = 0; am_tsplayer_input_source_type tsType = TS_MEMORY; am_tsplayer_input_buffer_type drmmode = TS_INPUT_BUFFER_TYPE_NORMAL; am_tsplayer_video_params vparam; am_tsplayer_audio_params aparam; am_tsplayer_init_params param = {tsType, drmmode, 0, 0}; if (prog->scrambled) { param.drmmode = TS_INPUT_BUFFER_TYPE_TVP; INF("enable local TVP\n"); } ret = AmTsPlayer_create(param, &session); ret |= AmTsPlayer_setSurface(session, (void *)&video_tunnel_id); ret |= AmTsPlayer_setWorkMode(session, TS_PLAYER_MODE_NORMAL); ret |= AmTsPlayer_registerCb(session, video_callback, NULL); if (prog->scrambled && !g_nosmp) { AmTsPlayer_setParams(session, AM_TSPLAYER_KEY_VIDEO_SECLEVEL, &seclev); AmTsPlayer_setParams(session, AM_TSPLAYER_KEY_AUDIO_SECLEVEL, &seclev); CA_DEBUG(1,"%s secure level: %#x\n ", __func__, seclev); } memset(&vparam, 0, sizeof(vparam)); vparam.codectype = prog->i_vformat; vparam.pid = prog->i_video_pid; ret |= AmTsPlayer_setVideoParams(session, &vparam); memset(&aparam, 0, sizeof(aparam)); aparam.codectype = prog->i_aformat; aparam.pid = prog->i_audio_pid; ret |= AmTsPlayer_setAudioParams(session, &aparam); if (vparam.pid != 0 && vparam.pid != 0x1fff) { ret |= AmTsPlayer_startVideoDecoding(session); ret |= AmTsPlayer_showVideo(session); ret |= AmTsPlayer_setTrickMode(session, AV_VIDEO_TRICK_MODE_NONE); } if (aparam.pid != 0 && aparam.pid != 0x1fff) { ret |= AmTsPlayer_startAudioDecoding(session); } play.player_session = session; INF("%s ret:%d, session:%#zx\n", __func__, ret, session); return 0; } static void *inject_thread(void *arg) { int fd; uint8_t* buf = (uint8_t*)malloc(inject_length * sizeof(uint8_t)); if (buf == NULL) { ERR("%s malloc FAILED\n", __func__); return NULL; } char *tspath = (char *)arg; const int kRwTimeout = 30000; am_tsplayer_input_buffer ibuf = {TS_INPUT_BUFFER_TYPE_NORMAL, (char *)buf, 0}; fd = open(tspath, O_RDONLY); INF("%s open %s, fd:%d\n", __func__, tspath, fd); if (fd == -1) { free(buf); return NULL; } while (gInjectRunning) { int retry = 100; int kRwSize = 0; am_tsplayer_result res; kRwSize = read(fd, buf, inject_length); if (kRwSize <= 0) { INF("%s read end of file, loop\n", __func__); lseek(fd, 0, SEEK_SET); continue; } ibuf.buf_size = kRwSize; do { res = AmTsPlayer_writeData(play.player_session, &ibuf, kRwTimeout); if (res == AM_TSPLAYER_ERROR_RETRY) { usleep(50000); } else { //INF("%#x Bytes injected\n", ibuf.buf_size); break; } } while(retry-- > 0); } free(buf); close(fd); INF("exit %s\n", __func__); return NULL; } static void *scbUpdate_thread(void *arg) { int tse_key_mode = -1; int dev_no = *(int*)arg; free (arg); int record_is_running =1; int error = 0; pthread_detach(pthread_self()); while (record_is_running) { if (recorder[dev_no].cas_session) { tse_key_mode = get_tse_key_mode(recorder[dev_no].cas_session); }else { INF("record [%d]has been closed. return", dev_no); return NULL; } switch (tse_key_mode) { case 0: case 2: tse_key_mode = 2; break; case 1: case 3: tse_key_mode = 3; break; default: INF("invalid tse key mode = %d. Quit scb thread! ", tse_key_mode); return NULL; } if (tse_key_mode != g_tse_key_mode[dev_no]) { INF("record [%d]:tse_key_mode update:%d -> %d\n", dev_no, g_tse_key_mode[dev_no], tse_key_mode); error = dvr_wrapper_ioctl_record(recorder[dev_no].dvr_session, DVR_RECORD_CMD_ENC_CHANGE_SCB , &tse_key_mode, sizeof(tse_key_mode)); if (error) { INF("Set scb fail = (%#x)", error); return NULL; } g_tse_key_mode[dev_no] = tse_key_mode; } usleep(400000);/* 400ms */ record_is_running = rec_status & (1 << dev_no); } INF("exit %s\n", __func__); return NULL; } static int dvb_init(void) { int ret; ret = AM_CA_Init(&g_cas_handle); ret |= AM_CA_RegisterEventCallback((CasSession)NULL, cas_event_cb); INF("CAS init ret = %d\r\n", ret); return ret; } static AM_RESULT cas_event_cb(CasSession session, char *json) { cJSON* cas; cJSON* input; cJSON* type; cJSON* state; UNUSED(session); INF("%s:%s\n", __func__, json); input = cJSON_Parse(json); if (input == NULL) { return -1; } cas = cJSON_GetObjectItemCaseSensitive(input, ITEM_CAS); if (!cJSON_IsString(cas) || (strcmp(cas->valuestring, VMX_CAS_STRING))) { INF("%s, not Verimatrix cas cmd\n", __func__); goto end; } type = cJSON_GetObjectItemCaseSensitive(input, ITEM_TYPE); if (!cJSON_IsString(type) || !type->valuestring) { INF("%s invalid cmd\n", __func__); goto end; } if (!strcmp(type->valuestring, ITEM_CHECK_PIN)) { check_pin_status = PIN_NEED_CHECK; INF("notify pin check status -> PIN_NEED_CHECK \n"); } else if (!strcmp(type->valuestring, ITEM_PIN_STATE)) { state = cJSON_GetObjectItemCaseSensitive(input, ITEM_ERROR_CODE); if (!cJSON_IsNumber(state)) { INF("%s invalid state type\n", __func__); goto end; } if (state) { check_pin_status = PIN_CHECK_SUCCESS; INF("notify pin check status -> PIN_CHECK_SUCCESS\n"); } else { check_pin_status = PIN_CHECK_FAILED; INF("notify pin check status -> PIN_CHECK_FAILED"); } } return 0; end: if (input) { cJSON_Delete(input); } return 0; } static DVR_Result_t encrypt_callback(DVR_CryptoParams_t *params, void *userdata) { int ret; CasSession cas_session = *(CasSession *)userdata; AM_CA_CryptoPara_t *cryptoPara = (AM_CA_CryptoPara_t *)params; struct timespec start_ts, end_ts; if (!cas_session) { ERR("%s invalid cas session\n", __func__); return -1; } clock_gettime(CLOCK_MONOTONIC, &start_ts); ret = AM_CA_DVREncrypt(cas_session, cryptoPara); if (ret) { cryptoPara->buf_len = 0; cryptoPara->buf_out.size = 0; ERR("%s failed\n", __func__); return -1; } if (cryptoPara->buf_len) { clock_gettime(CLOCK_MONOTONIC, &end_ts); CA_DEBUG(1,"%s AM_CA_DVREncrypt use (%lu) ms for (0x%x) bytes\n ", __func__, (end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) - (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000), cryptoPara->buf_len); } return 0; } static DVR_Result_t decrypt_block_callback(DVR_CryptoParams_t *params, void *userdata) { int ret; UNUSED(userdata); struct timespec start_ts, end_ts; AM_CA_CryptoPara_t *cryptoPara = (AM_CA_CryptoPara_t *)params; if (!play.replayed) { ret = AM_CA_DVRReplay(play.cas_session, cryptoPara); if (check_pin_status == PIN_NEED_CHECK) { do { //INF("wait state %d\n", check_pin_status); usleep(200*1000); } while (check_pin_status != PIN_CHECK_SUCCESS && running); ret = AM_CA_DVRReplay(play.cas_session, cryptoPara); } if (!ret) { play.replayed = 1; } else { cryptoPara->buf_len = cryptoPara->buf_in.size; cryptoPara->buf_out.size = cryptoPara->buf_in.size; return 0; } } clock_gettime(CLOCK_MONOTONIC, &start_ts); ret = AM_CA_DVRDecrypt(play.cas_session, cryptoPara); if (ret) { cryptoPara->buf_len = 0; cryptoPara->buf_out.size = 0; ERR("%s failed\n", __func__); return -1; } if (cryptoPara->buf_len) { //INF("%#x bytes decrypted\n", cryptoPara->buf_len); } if (cryptoPara->buf_len) { clock_gettime(CLOCK_MONOTONIC, &end_ts); CA_DEBUG(1,"%s AM_CA_DVRDecrypt use (%lu) ms for (0x%x) bytes.\n ", __func__, (end_ts.tv_sec*1000 + end_ts.tv_nsec/1000000) - (start_ts.tv_sec*1000 + start_ts.tv_nsec/1000000), cryptoPara->buf_len); } return 0; } static DVR_Result_t decrypt_tse_callback(DVR_CryptoParams_t *params, void *userdata) { int ret; UNUSED(userdata); AM_CA_CryptoPara_t *cryptoPara = (AM_CA_CryptoPara_t *)params; //INF("%s cryptoPara->new_position %d, cryptoPara->offset %lld. \n", __func__, cryptoPara->new_position, cryptoPara->offset); if ((cryptoPara->new_position) || (cryptoPara->offset == 0)) { INF("%sAM_CA_DVRReplay is called \n", __func__); ret = AM_CA_DVRReplay(play.cas_session, cryptoPara); if (!play.replayed) { if (check_pin_status == PIN_NEED_CHECK) { do { //INF("wait state %d\n", check_pin_status); usleep(200*1000); } while (check_pin_status != PIN_CHECK_SUCCESS && running); ret = AM_CA_DVRReplay(play.cas_session, cryptoPara); } if (!ret) { play.replayed = 1; } else { cryptoPara->buf_len = cryptoPara->buf_in.size; cryptoPara->buf_out.size = cryptoPara->buf_in.size; return 0; } } if (cryptoPara->offset != 0) { ret = AM_CA_DVRDecrypt(play.cas_session, cryptoPara); cryptoPara->buf_out.addr = cryptoPara->buf_in.addr; if (ret) { cryptoPara->buf_len = 0; cryptoPara->buf_out.size = 0; ERR("%s failed at line %d\n", __func__, __LINE__); return -1; } cryptoPara->new_position = 0; ret = AM_CA_DVRReplay(play.cas_session, cryptoPara); if (ret) { cryptoPara->buf_len = cryptoPara->buf_in.size; cryptoPara->buf_out.size = cryptoPara->buf_in.size; return 0; } } } ret = AM_CA_DVRDecrypt(play.cas_session, cryptoPara); cryptoPara->buf_out.addr = cryptoPara->buf_in.addr; #if 0 if (ret) { cryptoPara->buf_len = 0; cryptoPara->buf_out.size = 0; ERR("%s failed at line %d\n", __func__, __LINE__); return -1; } #endif return 0; } static DVR_Result_t RecEventHandler(DVR_RecordEvent_t event, void *params, void *userdata) { if (userdata != NULL) { DVR_WrapperRecordStatus_t *status = (DVR_WrapperRecordStatus_t *)params; UNUSED(status); switch (event) { case DVR_RECORD_EVENT_STATUS: //INF("Record event %d\n", status->state); break; default: //ERR("Unhandled recording event 0x%x from (%s)\n", event, (char *)userdata); break; } } return DVR_SUCCESS; } static void video_callback(void *user_data, am_tsplayer_event *event) { UNUSED(user_data); INF("video evt callback, type:%d\r\n", event?event->type:0); if (event == NULL) return; switch (event->type) { case AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED: INF("[evt] video changed\r\n"); break; case AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME: INF("[evt] first frame\r\n"); break; default: break; } } static DVR_Result_t PlayEventHandler(DVR_PlaybackEvent_t event, void *params, void *userdata) { UNUSED(params); if (userdata != NULL) { switch (event) { case DVR_PLAYBACK_EVENT_TRANSITION_OK: /**< Update the current player information*/ //log_play_evt((DVR_WrapperPlaybackStatus_t *)params, userdata); break; case DVR_PLAYBACK_EVENT_REACHED_END: /**< File player's EOF*/ //PLAY_EVT("EOF (%s)\n", (char *)userdata); break; default: //ERR("Unhandled event 0x%x from (%s)\n", event, (char *)userdata); break; } } return DVR_SUCCESS; } static void tsplayer_callback(void *user_data, am_tsplayer_event *event) { UNUSED(user_data); if (event) { switch (event->type) { case AM_TSPLAYER_EVENT_TYPE_PTS: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_PTS: stream_type:%d, pts[%llu]\n", event->event.pts.stream_type, event->event.pts.pts); break; } case AM_TSPLAYER_EVENT_TYPE_DTV_SUBTITLE: { uint8_t* pbuf = event->event.mpeg_user_data.data; uint32_t size = event->event.mpeg_user_data.len; INF("[evt] AM_TSPLAYER_EVENT_TYPE_DTV_SUBTITLE: %x-%x-%x-%x ,size %d\n", pbuf[0], pbuf[1], pbuf[2], pbuf[3], size); break; } case AM_TSPLAYER_EVENT_TYPE_USERDATA_CC: { uint8_t* pbuf = event->event.mpeg_user_data.data; uint32_t size = event->event.mpeg_user_data.len; INF("[evt] AM_TSPLAYER_EVENT_TYPE_USERDATA_CC: %x-%x-%x-%x ,size %d\n", pbuf[0], pbuf[1], pbuf[2], pbuf[3], size); break; } case AM_TSPLAYER_EVENT_TYPE_USERDATA_AFD: { uint8_t* pbuf = event->event.mpeg_user_data.data; uint32_t size = event->event.mpeg_user_data.len; INF("[evt] AM_TSPLAYER_EVENT_TYPE_USERDATA_AFD: %x-%x-%x-%x ,size %d\n", pbuf[0], pbuf[1], pbuf[2], pbuf[3], size); //USERDATA_AFD_t afd = *((USERDATA_AFD_t *)pbuf); //afd.reserved = afd.pts = 0; //INF("[evt] video afd changed: flg[0x%x] fmt[0x%x]\n", afd.af_flag, afd.af); break; } case AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED: [width:height] [%d x %d] @%d aspectratio[%d]\n", event->event.video_format.frame_width, event->event.video_format.frame_height, event->event.video_format.frame_rate, event->event.video_format.frame_aspectratio); break; } case AM_TSPLAYER_EVENT_TYPE_AUDIO_CHANGED: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_AUDIO_CHANGED: sample_rate:%d, channels:%d\n", event->event.audio_format.sample_rate, event->event.audio_format.channels); break; } case AM_TSPLAYER_EVENT_TYPE_DATA_LOSS: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_DATA_LOSS\n"); break; } case AM_TSPLAYER_EVENT_TYPE_DATA_RESUME: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_DATA_RESUME\n"); break; } case AM_TSPLAYER_EVENT_TYPE_SCRAMBLING: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_SCRAMBLING: stream_type:%d is_scramling[%d]\n", event->event.scramling.stream_type, event->event.scramling.scramling); break; } case AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME: { INF("[evt] AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME: ## VIDEO_AVAILABLE ##\n"); break; } default: break; } } } static int start_descrambling(dvb_service_info_t *prog) { int ret; AM_CA_ServiceInfo_t cas_para; CA_SERVICE_TYPE_t service_type = SERVICE_LIVE_PLAY; if (!prog->scrambled) return 0; ret = AM_CA_SetEmmPid(g_cas_handle, DMX_DEV_NO, prog->i_ca_pid); if (ret) { ERR("CAS set emm PID failed. ret = %d\r\n", ret); } ret = AM_CA_OpenSession(g_cas_handle, &play.cas_session, service_type); if (ret) { ERR("CAS open session failed. ret = %d\r\n", ret); return -1; } ret = AM_CA_RegisterEventCallback(play.cas_session, cas_event_cb); if (ret) { ERR("CAS RegisterEventCallback failed. ret = %d\r\n", ret); } memset(&cas_para, 0x0, sizeof(AM_CA_ServiceInfo_t)); if (prog->service_type == IPTV_TYPE) { cas_para.service_mode = SERVICE_IPTV; INF("IPTV service mode:%d\n", cas_para.service_mode); } else { cas_para.service_mode = SERVICE_DVB; INF("DVB service mode:%d\n", cas_para.service_mode); } cas_para.service_id = prog->i_program_num; cas_para.service_type = SERVICE_LIVE_PLAY; cas_para.ecm_pid = prog->i_ecm_pid[0]; cas_para.stream_pids[0] = prog->i_video_pid; cas_para.stream_pids[1] = prog->i_audio_pid; cas_para.stream_num = 2; if (prog->private_data[0]) { memcpy(cas_para.ca_private_data, prog->private_data, prog->private_data[0]); } cas_para.ca_private_data_len = prog->private_data[0]; ret = AM_CA_StartDescrambling(play.cas_session, &cas_para); if (ret) { ERR("CAS start descrambling failed. ret = %d\r\n", ret); return -1; } INF("CAS started\r\n"); return 0; } static int start_liveplay(dvb_service_info_t *prog) { uint32_t num = 0; am_tsplayer_result ret; am_tsplayer_video_params vparam; am_tsplayer_audio_params aparam; am_tsplayer_init_params param; am_tsplayer_avsync_mode avsyncmode = TS_SYNC_PCRMASTER; am_tsplayer_handle player_session = 0; INF("vpid:%#x vfmt:%d apid:%#x afmt:%d ecmpid:%#x emmpid:%#x scramble:%d\r\n", prog->i_video_pid, prog->i_vformat, prog->i_audio_pid, prog->i_aformat, prog->i_ecm_pid[0], prog->i_ca_pid, prog->scrambled); memset(¶m, 0 , sizeof(am_tsplayer_init_params)); param.source = TS_DEMOD; param.dmx_dev_id = DMX_DEV_NO; if (prog->scrambled && !g_nosmp) { param.drmmode = TS_INPUT_BUFFER_TYPE_TVP; INF("enable live TVP\n"); } ret = AmTsPlayer_create(param, &player_session); if (ret != AM_TSPLAYER_OK) { CA_DEBUG(0, "Create tsplayer failed!!!! err:%x", ret); return -1; } play.player_session = player_session; if (prog->scrambled && !g_nosmp) { AmTsPlayer_setParams(player_session, AM_TSPLAYER_KEY_VIDEO_SECLEVEL, &seclev); AmTsPlayer_setParams(player_session, AM_TSPLAYER_KEY_AUDIO_SECLEVEL, &seclev); CA_DEBUG(1,"%s secure level: %#x\n ", __func__, seclev); } INF("AmTsPlayer_setSurface player_session is %#zx, video_tunnel_id is 0x%d\n", player_session, video_tunnel_id); ret = AmTsPlayer_setSurface(player_session, (void *)&video_tunnel_id); ret |= AmTsPlayer_getInstansNo(player_session, &num); ret |= AmTsPlayer_setWorkMode(player_session, TS_PLAYER_MODE_NORMAL); ret |= AmTsPlayer_registerCb(player_session, video_callback, NULL); ret |= AmTsPlayer_setSyncMode(player_session, avsyncmode); // ret |= AmTsPlayer_setVideoWindow(player_session, 0, 0, 1280, 720); #ifdef ANDROID am_tsplayer_audio_patch_manage_mode audio_mode = AUDIO_PATCH_MANAGE_FORCE_ENABLE; ret |= AmTsPlayer_setParams(player_session, AM_TSPLAYER_KEY_SET_AUDIO_PATCH_MANAGE_MODE, &audio_mode); #endif INF("create tsplayer success. session:%#zx instance_no:%d ret:%d\r\n", player_session, num, ret); memset(&vparam, 0, sizeof(vparam)); vparam.codectype = prog->i_vformat; vparam.pid = prog->i_video_pid; AmTsPlayer_setVideoParams(player_session, &vparam); AmTsPlayer_startVideoDecoding(player_session); memset(&aparam, 0, sizeof(aparam)); aparam.codectype = prog->i_aformat; aparam.pid = prog->i_audio_pid; AmTsPlayer_setAudioParams(player_session, &aparam); AmTsPlayer_startAudioDecoding(player_session); AmTsPlayer_showVideo(player_session); AmTsPlayer_setTrickMode(player_session, AV_VIDEO_TRICK_MODE_NONE); return 0; } static int stop_liveplay(void) { INF("stop_liveplay==\n"); if (play.cas_session) { AM_CA_StopDescrambling(play.cas_session); AM_CA_CloseSession(play.cas_session); } AmTsPlayer_stopAudioDecoding(play.player_session); AmTsPlayer_stopVideoDecoding(play.player_session); AmTsPlayer_release(play.player_session); memset(&play, 0, sizeof(CasTestSession)); return 0; } static int start_recording(int dev_no, dvb_service_info_t *prog, char *tspath) { DVR_WrapperRecordOpenParams_t rec_open_params; DVR_WrapperRecordStartParams_t rec_start_params; DVR_WrapperPidsInfo_t *pids_info; bool tse_mode = false; //char cmd[256]; int error; AM_CA_ServiceInfo_t cas_para; CA_SERVICE_TYPE_t service_type = SERVICE_PVR_RECORDING; UNUSED(dev_no); DVR_WrapperRecord_t recorder_session = NULL; if (dev_no >= MAX_REC_NUM) { ERR("wrong device no %d\n", dev_no); return -1; } memset(&rec_open_params, 0, sizeof(DVR_WrapperRecordOpenParams_t)); rec_open_params.dmx_dev_id = dev_no; rec_open_params.segment_size = 100 * 1024 * 1024;/*100MB*/ rec_open_params.max_size = size; rec_open_params.max_time = duration; rec_open_params.event_fn = RecEventHandler; rec_open_params.event_userdata = "rec0"; rec_open_params.flags = 0; rec_open_params.force_sysclock = true; if (g_nosmp == 1) { rec_open_params.flush_size = 188 * 1024; } if (is_timeshifting(mode)) { rec_open_params.flags |= DVR_RECORD_FLAG_ACCURATE; service_type = SERVICE_PVR_TIMESHIFT_RECORDING; } strncpy(rec_open_params.location, tspath, sizeof(rec_open_params.location)); rec_open_params.location[sizeof(rec_open_params.location)-1] = '\0'; rec_open_params.is_timeshift = (is_timeshifting(mode)) ? DVR_TRUE : DVR_FALSE; if (prog->scrambled) { rec_open_params.crypto_data = &recorder[dev_no].cas_session; rec_open_params.crypto_fn = encrypt_callback; } error = dvr_wrapper_open_record(&recorder_session, &rec_open_params); if (error) { ERR( "recorder open fail = (0x%x)\n", error); return -1; } recorder[dev_no].dvr_session = (void *)recorder_session; INF( "Starting %s recording %p [%ld secs/%llu bytes] [%s.ts]\n", (is_timeshifting(mode))? "timeshift" : "normal", recorder_session, rec_open_params.max_time, rec_open_params.max_size, rec_open_params.location); memset(&rec_start_params, 0, sizeof(rec_start_params)); if (prog->scrambled) { void *buf = NULL; uint32_t secmem_size = block_size*20; SecMemHandle secmem_session; error = AM_CA_OpenSession(g_cas_handle, &recorder[dev_no].cas_session, service_type); if (error) { ERR("CAS open session failed. ret = %d\r\n", error); dvr_wrapper_close_record(recorder_session); return -1; } error = AM_CA_RegisterEventCallback(recorder[dev_no].cas_session, cas_event_cb); if (error) { ERR("CAS RegisterEventCallback failed. ret = %d\r\n", error); } // tse_mode = get_cas_mode(recorder[dev_no].cas_session); if (g_vm_config.run) { watermark_test_config(g_vm_config.on, g_vm_config.config, g_vm_config.strength); } if (g_oc_config.run) { output_control_test_config(g_oc_config.flag, g_oc_config.analog, g_oc_config.cgmsa, g_oc_config.emicci); } INF("set AM_CA_SetEmmPid: %#x\n", prog->i_ca_pid); error = AM_CA_SetEmmPid(g_cas_handle, dev_no, prog->i_ca_pid); if (error) { ERR("CAS set emm PID failed. ret = %d\r\n", error); return -1; } memset(&cas_para, 0x0, sizeof(AM_CA_ServiceInfo_t)); cas_para.dmx_dev = dev_no; cas_para.service_id = prog->i_program_num; cas_para.service_type = service_type; cas_para.ecm_pid = prog->i_ecm_pid[0]; cas_para.stream_pids[0] = prog->i_video_pid; cas_para.stream_pids[1] = prog->i_audio_pid; cas_para.stream_num = 2; if (prog->private_data[0]) { // parser algo from pmt, use for descramble memcpy(cas_para.ca_private_data, prog->private_data, prog->private_data[0]); } cas_para.ca_private_data_len = prog->private_data[0]; INF("start_recording,i_program_num=%d,ca_private_data[0]=%d,[2]=0x%x,vpid=0x%x,apid=0x%x\n", prog->i_program_num, cas_para.ca_private_data[0], cas_para.ca_private_data[2], prog->i_video_pid, prog->i_audio_pid); if (prog->service_type == IPTV_TYPE) { cas_para.service_mode = SERVICE_IPTV; INF("IPTV service mode:%d\n", cas_para.service_mode); } else { cas_para.service_mode = SERVICE_DVB; INF("DVB service mode:%d\n", cas_para.service_mode); } error = AM_CA_DVRStart(recorder[dev_no].cas_session, &cas_para); if (error) { ERR("CAS start DVR failed. ret = %d\r\n", error); AM_CA_CloseSession(recorder[dev_no].cas_session); recorder[dev_no].cas_session = 0; dvr_wrapper_close_record(recorder_session); return -1; } if (false == tse_mode && !g_nosmp) { secmem_session = AM_CA_CreateSecmem( recorder[dev_no].cas_session, service_type, &buf, &secmem_size); if (!secmem_session) { ERR("create dvr recording secmem failed\n"); dvr_wrapper_close_record(recorder_session); return -1; } recorder[dev_no].secmem_session = secmem_session; INF("set dvr recording secmem addr:%#zx size:%#x\n", (size_t)buf, secmem_size); error = dvr_wrapper_set_record_secure_buffer(recorder_session, buf, secmem_size); if (error) { ERR("dvr_wrapper_set_record_secure_buffer failed\n"); dvr_wrapper_close_record(recorder_session); AM_CA_DestroySecmem(recorder[dev_no].cas_session, secmem_session); recorder[dev_no].secmem_session = (SecMemHandle)NULL; return -1; } } } pids_info = &rec_start_params.pids_info; pids_info->nb_pids = 2; pids_info->pids[0].pid = prog->i_video_pid; pids_info->pids[1].pid = prog->i_audio_pid; DVR_VideoFormat_t dvb_vfmt; if (!convert_video_codec_fmt_am2dvb(prog->i_vformat, &dvb_vfmt)) { ERR("can not convert am video codec type(%d) to dtv", prog->i_vformat); } pids_info->pids[0].type = DVR_STREAM_TYPE_VIDEO << 24 | dvb_vfmt; DVR_AudioFormat_t dvb_afmt; if (!convert_audio_codec_fmt_am2dvb(prog->i_aformat, &dvb_afmt)) { ERR("can not convert am audio codec type(%d) to dtv", prog->i_aformat); } pids_info->pids[1].type = DVR_STREAM_TYPE_AUDIO << 24 | dvb_afmt; error = dvr_wrapper_start_record(recorder_session, &rec_start_params); if (error) { ERR( "recorder start fail = (0x%x)\n", error); dvr_wrapper_close_record(recorder_session); if (false == tse_mode && !g_nosmp) { AM_CA_DestroySecmem(recorder[dev_no].cas_session, recorder[dev_no].secmem_session); recorder[dev_no].secmem_session = (SecMemHandle)NULL; } AM_CA_CloseSession(recorder[dev_no].cas_session); recorder[dev_no].cas_session = 0; return -1; } return 0; } static int start_tse_recording(int dev_no, dvb_service_info_t *prog, char *tspath) { DVR_WrapperRecordOpenParams_t rec_open_params; DVR_WrapperRecordStartParams_t rec_start_params; DVR_WrapperPidsInfo_t *pids_info; bool tse_mode = true; int tse_key_mode = -1; //char cmd[256]; int error; AM_CA_ServiceInfo_t cas_para; CA_SERVICE_TYPE_t service_type = SERVICE_PVR_RECORDING; UNUSED(dev_no); DVR_WrapperRecord_t recorder_session = NULL; if (dev_no >= MAX_REC_NUM) { ERR("wrong device no %d\n", dev_no); return -1; } memset(&rec_open_params, 0, sizeof(DVR_WrapperRecordOpenParams_t)); rec_open_params.dmx_dev_id = dev_no; rec_open_params.segment_size = 188 * 1024 * 1024;/*188MB*/ rec_open_params.max_size = size; rec_open_params.max_time = duration; rec_open_params.event_fn = RecEventHandler; rec_open_params.event_userdata = "rec0"; rec_open_params.flags = 0; rec_open_params.force_sysclock = true; rec_open_params.flush_size = 188 * 1024; if (is_timeshifting(mode)) { rec_open_params.flags |= DVR_RECORD_FLAG_ACCURATE; service_type = SERVICE_PVR_TIMESHIFT_RECORDING; } rec_open_params.flags |= DVR_RECORD_FLAG_INDEXED; strncpy(rec_open_params.location, tspath, sizeof(rec_open_params.location)); rec_open_params.location[sizeof(rec_open_params.location)-1] = '\0'; rec_open_params.is_timeshift = (is_timeshifting(mode)) ? DVR_TRUE : DVR_FALSE; if (prog->scrambled) { rec_open_params.flags |= DVR_RECORD_FLAG_EXT_TSEENC; rec_open_params.flags |= DVR_RECORD_FLAG_SCRAMBLED; rec_open_params.crypto_data = &recorder[dev_no].cas_session; rec_open_params.crypto_fn = encrypt_callback; if (dev_no == 0 || dev_no == 1) { rec_open_params.tse_dmx_dev_id = 4; rec_open_params.fta_dmx_dev_id = 5; } else if(dev_no == 2) { rec_open_params.tse_dmx_dev_id = 6; rec_open_params.fta_dmx_dev_id = 7; } else { ERR( "recorder open fail. don't support this dev = (0x%x)\n", dev_no); return -1; } } error = dvr_wrapper_open_record(&recorder_session, &rec_open_params); if (error) { ERR( "recorder open fail = (0x%x)\n", error); return -1; } recorder[dev_no].dvr_session = (void *)recorder_session; INF( "Starting %s recording %p [%ld secs/%llu bytes] [%s.ts]\n", (is_timeshifting(mode))? "timeshift" : "normal", recorder_session, rec_open_params.max_time, rec_open_params.max_size, rec_open_params.location); memset(&rec_start_params, 0, sizeof(rec_start_params)); if (prog->scrambled) { void *buf = NULL; error = AM_CA_OpenSession(g_cas_handle, &recorder[dev_no].cas_session, service_type); if (error) { ERR("CAS open session failed. ret = %d\r\n", error); dvr_wrapper_close_record(recorder_session); return -1; } error = AM_CA_RegisterEventCallback(recorder[dev_no].cas_session, cas_event_cb); if (error) { ERR("CAS RegisterEventCallback failed. ret = %d\r\n", error); } // tse_mode = get_cas_mode(recorder[dev_no].cas_session); // INF("get_cas_mode return tse_mode: %d\r\n", tse_mode); if (g_vm_config.run) { watermark_test_config(g_vm_config.on, g_vm_config.config, g_vm_config.strength); } if (g_oc_config.run) { output_control_test_config(g_oc_config.flag, g_oc_config.analog, g_oc_config.cgmsa, g_oc_config.emicci); } INF("set AM_CA_SetEmmPid: %#x\n", prog->i_ca_pid); error = AM_CA_SetEmmPid(g_cas_handle, dev_no, prog->i_ca_pid); if (error) { ERR("CAS set emm PID failed. ret = %d\r\n", error); return -1; } memset(&cas_para, 0x0, sizeof(AM_CA_ServiceInfo_t)); cas_para.dmx_dev = dev_no; cas_para.dvr_dev = rec_open_params.tse_dmx_dev_id; cas_para.service_id = prog->i_program_num; cas_para.service_type = service_type; cas_para.ecm_pid = prog->i_ecm_pid[0]; cas_para.stream_pids[0] = prog->i_video_pid; cas_para.stream_pids[1] = prog->i_audio_pid; cas_para.stream_num = 2; if (prog->private_data[0]) { // parser algo from pmt, use for descramble memcpy(cas_para.ca_private_data, prog->private_data, prog->private_data[0]); } cas_para.ca_private_data_len = prog->private_data[0]; INF("start_recording,i_program_num=%d,ca_private_data[0]=%d,[2]=0x%x,vpid=0x%x,apid=0x%x\n", prog->i_program_num, cas_para.ca_private_data[0], cas_para.ca_private_data[2], prog->i_video_pid, prog->i_audio_pid); if (prog->service_type == IPTV_TYPE) { cas_para.service_mode = SERVICE_IPTV; INF("IPTV service mode:%d\n", cas_para.service_mode); } else { cas_para.service_mode = SERVICE_DVB; INF("DVB service mode:%d\n", cas_para.service_mode); } error = AM_CA_DVRStart(recorder[dev_no].cas_session, &cas_para); if (error) { ERR("CAS start DVR failed. ret = %d\r\n", error); AM_CA_CloseSession(recorder[dev_no].cas_session); recorder[dev_no].cas_session = 0; dvr_wrapper_close_record(recorder_session); return -1; } if (true == tse_mode) { tse_key_mode = get_tse_key_mode(recorder[dev_no].cas_session); INF("get_tse_key_mode return tse_key_mode:%d\n", tse_key_mode); switch (tse_key_mode) { case 0: case 2: tse_key_mode = 2; break; case 1: case 3: tse_key_mode = 3; break; default: INF("invalid tse key mode = %d", tse_key_mode); dvr_wrapper_close_record(recorder_session); return -1; } error = dvr_wrapper_ioctl_record(recorder_session, DVR_RECORD_CMD_ENC_CHANGE_SCB , &tse_key_mode, sizeof(tse_key_mode)); if (error) { INF("Set scb fail = (%#x)", error); dvr_wrapper_close_record(recorder_session); return -1; } g_tse_key_mode[dev_no] = tse_key_mode; } } pids_info = &rec_start_params.pids_info; pids_info->nb_pids = 2; pids_info->pids[0].pid = prog->i_video_pid; pids_info->pids[1].pid = prog->i_audio_pid; DVR_VideoFormat_t dvb_vfmt; if (!convert_video_codec_fmt_am2dvb(prog->i_vformat, &dvb_vfmt)) { ERR("can not convert am video codec type(%d) to dtv", prog->i_vformat); } pids_info->pids[0].type = DVR_STREAM_TYPE_VIDEO << 24 | dvb_vfmt; DVR_AudioFormat_t dvb_afmt; if (!convert_audio_codec_fmt_am2dvb(prog->i_aformat, &dvb_afmt)) { ERR("can not convert am audio codec type(%d) to dtv", prog->i_aformat); } pids_info->pids[1].type = DVR_STREAM_TYPE_AUDIO << 24 | dvb_afmt; if (prog->scrambled && true == tse_mode) { pids_info->pids[0].type |= 3 << 22; pids_info->pids[1].type |= 3 << 22; } error = dvr_wrapper_start_record(recorder_session, &rec_start_params); if (error) { ERR( "recorder start fail = (0x%x)\n", error); dvr_wrapper_close_record(recorder_session); if (recorder[dev_no].cas_session) { AM_CA_DVRStop(recorder[dev_no].cas_session); AM_CA_CloseSession(recorder[dev_no].cas_session); } recorder[dev_no].cas_session = 0; return -1; } #if 1 /* test to not set scb. */ if (prog->scrambled) { int * args = (int*)malloc(sizeof(int)); *args = dev_no; pthread_create(&gScbUpdateThread[dev_no], NULL, scbUpdate_thread, args); } #endif return 0; } static bool get_cas_mode(CasSession session) { bool is_tse_mode = false; cJSON *input = NULL; cJSON *item = NULL; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; if (session) AM_CA_Ioctl(session, IOCTRL_INVOKE_GET_CAS_MODE, out_json, MAX_JSON_LEN); //INF("%s, IOCTRL_INVOKE_GET_CAS_MODE:%s\n, out_json=%s\n", __func__, IOCTRL_INVOKE_GET_CAS_MODE, out_json); input = cJSON_Parse(out_json); item = cJSON_GetObjectItemCaseSensitive(input, ITEM_DVR_CAS_MODE); if (!cJSON_IsString(item) || item->valuestring[0] == '\0') { INF("Get cas mode failed, default r2r mode,is_tse_mode=%d\n",is_tse_mode); } else { if (strncmp(item->valuestring, "r2r", 3) == 0) { is_tse_mode = false; } else if (strncmp(item->valuestring, "tse", 3) == 0) { is_tse_mode = true; } //INF("%s: string: %s, is_tse_mode=%d\n", __func__, item->valuestring, is_tse_mode); } cJSON_Delete(input); return is_tse_mode; } static int set_cas_mode(uint8_t is_tse_mode) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; INF("set_cas_mode to tse: %d\n\n", is_tse_mode); input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_SET_CAS_MODE); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(is_tse_mode); cJSON_AddItemToObject(input, ITEM_DVR_CAS_MODE, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); AM_CA_Ioctl(0, in_json, out_json, MAX_JSON_LEN); INF("out_json:\n%s\n", out_json); return 0; } static int get_tse_key_mode(CasSession session) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; int tse_key_mode = -1; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_GET_TSE_KEY_MODE); cJSON_AddItemToObject(input, ITEM_CMD, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); if (session) AM_CA_Ioctl(session, in_json, out_json, MAX_JSON_LEN); //INF("ITEM_GET_TSE_KEY_MODE,in_json:%s,out_json=%s\n", in_json, out_json); cJSON_Delete(input); input = cJSON_Parse(out_json); item = cJSON_GetObjectItemCaseSensitive(input, ITEM_TSE_KEY_MODE); //INF("get_tse_key_mode: item->type : %d, item->valueint: %d, item->valueint: %f, item->valuestring: %s\n", item->type, item->valueint, item->valuedouble, item->valuestring); tse_key_mode = item->valueint; cJSON_Delete(input); return tse_key_mode; } static int show_cardno(void) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_GETSCNO); cJSON_AddItemToObject(input, ITEM_CMD, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); INF("show_cardno,in_json:%s,out_json=%s\n", in_json, out_json); cJSON_Delete(input); input = cJSON_Parse(out_json); item = cJSON_GetObjectItemCaseSensitive(input, ITEM_CARDNO); if (!cJSON_IsString(item) || item->valuestring[0] == '\0') { cJSON_Delete(input); INF("Get card no failed\n"); return -1; } INF("cardno:%s\n", item->valuestring); cJSON_Delete(input); return 0; } static int show_boxid(void) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_GETBOXID); cJSON_AddItemToObject(input, ITEM_CMD, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); cJSON_Delete(input); input = cJSON_Parse(out_json); item = cJSON_GetObjectItemCaseSensitive(input, ITEM_BOXID); if (!cJSON_IsString(item) || item->valuestring[0] == '\0') { cJSON_Delete(input); INF("Get box id failed\n"); return -1; } INF("boxid:%s\n", item->valuestring); cJSON_Delete(input); return 0; } static int check_pin(char *pin, uint8_t pinIndex, uint8_t reason, uint8_t dvrChannel) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; CasSession cas_session; memset(&cas_session, 0, sizeof(CasSession)); input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_CHECK_PIN); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateString(pin); cJSON_AddItemToObject(input, ITEM_PIN, item); item = cJSON_CreateNumber(pinIndex); cJSON_AddItemToObject(input, ITEM_PIN_INDEX, item); item = cJSON_CreateNumber(reason); cJSON_AddItemToObject(input, ITEM_REASON, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (dvrChannel == 0) { cas_session = recorder[0].cas_session; }else if (dvrChannel == 1) { cas_session = recorder[1].cas_session; }else { cas_session = play.cas_session; } if (cas_session) { AM_CA_Ioctl(cas_session, in_json, out_json, MAX_JSON_LEN); INF("out_json:\n%s\n", out_json); } return 0; } static int dvr_test_config(uint8_t algo) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_SET_ALGO); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(algo); cJSON_AddItemToObject(input, ITEM_ALGO, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); AM_CA_Ioctl(recorder[0].cas_session, in_json, out_json, MAX_JSON_LEN); INF("out_json:\n%s\n", out_json); return 0; } static int watermark_test_config( uint8_t on, uint8_t config, uint8_t strength) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; int i; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_WATERMARK); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(on); cJSON_AddItemToObject(input, ITEM_ON, item); item = cJSON_CreateNumber(config); cJSON_AddItemToObject(input, ITEM_CONFIG, item); item = cJSON_CreateNumber(strength); cJSON_AddItemToObject(input, ITEM_STRENGTH, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (has_live(mode) && play.cas_session) { INF("has live\n"); AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); } for (i = 0; i < MAX_REC_NUM; i++) { if (recorder[i].cas_session) { INF("has recording%d\n", i); AM_CA_Ioctl(recorder[i].cas_session, in_json, out_json, MAX_JSON_LEN); } } INF("out_json:\n%s\n", out_json); return 0; } static int output_control_test_config( uint32_t flag, uint8_t analog, uint8_t cgmsa, uint8_t emicci) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; int i; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_OUTPUT_CONTROL); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(flag); cJSON_AddItemToObject(input, ITEM_FLAG, item); item = cJSON_CreateNumber(analog); cJSON_AddItemToObject(input, ITEM_ANALOG, item); item = cJSON_CreateNumber(cgmsa); cJSON_AddItemToObject(input, ITEM_CGMSA, item); item = cJSON_CreateNumber(emicci); cJSON_AddItemToObject(input, ITEM_EMICCI, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (has_live(mode) && play.cas_session) { INF("has live\n"); AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); } for (i = 0; i < MAX_REC_NUM; i++) { if (recorder[i].cas_session) { INF("has recording%d\n", i); AM_CA_Ioctl(recorder[i].cas_session, in_json, out_json, MAX_JSON_LEN); } } INF("out_json:\n%s\n", out_json); return 0; } static int svp_test_config(size_t addr) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_SVP); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(addr); cJSON_AddItemToObject(input, ITEM_ADDR, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (has_live(mode)) { AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); INF("out_json:\n%s\n", out_json); } return 0; } static int antirollback_test_config(uint8_t flag) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_ARB); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(flag); cJSON_AddItemToObject(input, ITEM_FLAG, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (has_live(mode)) { AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); INF("out_json:\n%s\n", out_json); } return 0; } static int ta2ta_test_config( uint32_t clientid, const char *data, uint32_t len) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_TA2TA); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(clientid); cJSON_AddItemToObject(input, ITEM_CLIENTID, item); item = cJSON_CreateString(data); cJSON_AddItemToObject(input, ITEM_DATA, item); item = cJSON_CreateNumber(len); cJSON_AddItemToObject(input, ITEM_LEN, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (has_live(mode)) { AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); INF("out_json:\n%s\n", out_json); } return 0; } static int hdcp_test_config(uint8_t svc_idx) { cJSON *input = NULL; cJSON *item = NULL; char in_json[MAX_JSON_LEN]; in_json[0] = '\0'; char out_json[MAX_JSON_LEN]; out_json[0] = '\0'; input = cJSON_CreateObject(); item = cJSON_CreateString(VMX_CAS_STRING); cJSON_AddItemToObject(input, ITEM_CAS, item); item = cJSON_CreateString(ITEM_HDCP); cJSON_AddItemToObject(input, ITEM_CMD, item); item = cJSON_CreateNumber(svc_idx); cJSON_AddItemToObject(input, ITEM_SERVICE_INDEX, item); cJSON_PrintPreallocated(input, in_json, MAX_JSON_LEN, 1); INF("in_json:\n%s\n", in_json); if (play.cas_session) { AM_CA_Ioctl(play.cas_session, in_json, out_json, MAX_JSON_LEN); } INF("out_json:\n%s\n", out_json); return 0; } static int stop_recording(int dev_no) { int ret; CasSession cas_session = recorder[dev_no].cas_session; bool tse_mode = g_indexer; INF("stop_recording, dev_no=%d\n", dev_no); if (dev_no >= MAX_REC_NUM) { ERR("wrong device no %d\n", dev_no); return -1; } ret = dvr_wrapper_stop_record((DVR_WrapperRecord_t *)recorder[dev_no].dvr_session); ret |= dvr_wrapper_close_record((DVR_WrapperRecord_t *)recorder[dev_no].dvr_session); if (ret) { ERR("stop/close record failed:%d\n", ret); return -1; } if (cas_session) { // bool tse_mode = get_cas_mode(cas_session); AM_CA_DVRStop(cas_session); if (!tse_mode && !g_nosmp) { ret = AM_CA_DestroySecmem(cas_session, recorder[dev_no].secmem_session); if (ret) { ERR("destroy secmem failed:%d\n", ret); return -1; } } AM_CA_CloseSession(cas_session); } memset(&recorder[dev_no], 0, sizeof(CasTestSession)); return 0; } static int stop_tse_recording(int dev_no) { int ret; CasSession cas_session = recorder[dev_no].cas_session; INF("stop_tse_recording, dev_no=%d\n", dev_no); if (dev_no >= MAX_REC_NUM) { ERR("wrong device no %d\n", dev_no); return -1; } ret = dvr_wrapper_stop_record((DVR_WrapperRecord_t *)recorder[dev_no].dvr_session); ret |= dvr_wrapper_close_record((DVR_WrapperRecord_t *)recorder[dev_no].dvr_session); if (ret) { ERR("stop/close record failed:%d\n", ret); return -1; } if (cas_session) { AM_CA_DVRStop(cas_session); AM_CA_CloseSession(cas_session); } memset(&recorder[dev_no], 0, sizeof(CasTestSession)); g_tse_key_mode[dev_no] = -1; return 0; } static int get_dvr_info(char *location, int *apid, int *afmt, int *vpid, int *vfmt) { uint32_t segment_nb = 0; uint64_t *p_segment_ids = NULL; DVR_RecordSegmentInfo_t seg_info; int error; int aid = 0x1fff, vid = 0x1fff; int aft = 0, vft = 0; memset(&seg_info, 0, sizeof(DVR_RecordSegmentInfo_t)); error = dvr_segment_get_list(location, &segment_nb, &p_segment_ids); if (!error && segment_nb) { error = dvr_segment_get_info(location, p_segment_ids[0], &seg_info); free(p_segment_ids); } if (!error) { int i; for (i = 0; i < seg_info.nb_pids; i++) { switch (DVR_STREAM_TYPE_TO_TYPE(seg_info.pids[i].type)) { case DVR_STREAM_TYPE_VIDEO: vid = seg_info.pids[i].pid; vft = DVR_STREAM_TYPE_TO_FMT(seg_info.pids[i].type); INF("type(0x%x)[video] pid(0x%x) fmt(%d)\n", DVR_STREAM_TYPE_TO_TYPE(seg_info.pids[i].type), seg_info.pids[i].pid, DVR_STREAM_TYPE_TO_FMT(seg_info.pids[i].type) ); break; case DVR_STREAM_TYPE_AUDIO: aid = seg_info.pids[i].pid; aft = DVR_STREAM_TYPE_TO_FMT(seg_info.pids[i].type); INF("type(0x%x)[audio] pid(0x%x) fmt(%d)\n", DVR_STREAM_TYPE_TO_TYPE(seg_info.pids[i].type), seg_info.pids[i].pid, DVR_STREAM_TYPE_TO_FMT(seg_info.pids[i].type) ); break; default: INF("type(0x%x) pid(0x%x) fmt(%d)\n", DVR_STREAM_TYPE_TO_TYPE(seg_info.pids[i].type), seg_info.pids[i].pid, DVR_STREAM_TYPE_TO_FMT(seg_info.pids[i].type) ); break; } } } if (apid) *apid = aid; if (afmt) *afmt = aft; if (vpid) *vpid = vid; if (vfmt) *vfmt = vft; return 0; } static int start_playback(void *params, int scrambled, int pause) { DVR_WrapperPlayback_t player = NULL; DVR_PlaybackPids_t play_pids; DVR_WrapperPlaybackOpenParams_t play_params; am_tsplayer_handle tsplayer_handle = 0; int vpid = 1024, apid = 1025, vfmt = 0, afmt = 0; bool tse_mode = false; int error; void *sec_buf = NULL; uint32_t sec_buf_size = inject_length + 4*1024; CA_SERVICE_TYPE_t service_type = SERVICE_PVR_PLAY; INF("start_playback,0- sec_buf_size:%d\n", sec_buf_size); memset(&play_params, 0, sizeof(play_params)); memset(&play_pids, 0, sizeof(play_pids)); play_pids.video.type = DVR_STREAM_TYPE_VIDEO; play_pids.audio.type = DVR_STREAM_TYPE_AUDIO; if (is_timeshifting(mode)) { dvb_service_info_t *prog = (dvb_service_info_t *)params; strncpy(play_params.location, pfilename, sizeof(play_params.location)); play_params.location[sizeof(play_params.location)-1] = '\0'; play_params.is_timeshift = DVR_TRUE; play_params.dmx_dev_id = DMX_DEV_NO_2ND; vpid = prog->i_video_pid; DVR_VideoFormat_t dvb_vfmt; if (!convert_video_codec_fmt_am2dvb(prog->i_vformat, &dvb_vfmt)) { ERR("can not convert am video codec type(%d) to dtv", prog->i_vformat); } vfmt = dvb_vfmt; apid = prog->i_audio_pid; DVR_AudioFormat_t dvb_afmt; if (!convert_audio_codec_fmt_am2dvb(prog->i_aformat, &dvb_afmt)) { ERR("can not convert am audio codec type(%d) to dtv", prog->i_aformat); } afmt = dvb_afmt; service_type = SERVICE_PVR_TIMESHIFT_PLAY; } else { strncpy(play_params.location, params, sizeof(play_params.location)); play_params.location[sizeof(play_params.location)-1] = '\0'; play_params.is_timeshift = DVR_FALSE; play_params.dmx_dev_id = DMX_DEV_NO; get_dvr_info(params, &apid, &afmt, &vpid, &vfmt); } INF("vpid:%#x vfmt:%d apid:%#x afmt:%d\n", vpid, vfmt, apid, afmt); if (scrambled) { error = AM_CA_OpenSession( g_cas_handle, &play.cas_session, service_type); INF("%s open cas session:%#zx, start cas, return:%d\n", __func__, play.cas_session, error); if (error) { ERR("CAS open session failed. ret = %d\r\n", error); return -1; } AM_CA_RegisterEventCallback(play.cas_session, cas_event_cb); // dvr playback need set demux id to cas hal plugin AM_CA_PreParam_t preParam; preParam.dmx_dev = play_params.dmx_dev_id; AM_CA_DVRSetPreParam(play.cas_session, &preParam); // tse_mode = get_cas_mode(play.cas_session); if (!tse_mode && !g_nosmp) { play.secmem_session = AM_CA_CreateSecmem( play.cas_session, service_type, &sec_buf, &sec_buf_size); if (!play.secmem_session) { ERR("cas playback failed. secmem_session:%#zx\n", play.secmem_session); } } } play_pids.video.pid = vpid; play_pids.video.format = vfmt; play_pids.audio.pid = apid; play_pids.audio.format = afmt; play_params.event_fn = PlayEventHandler; play_params.event_userdata = "play0"; /*open TsPlayer*/ { uint32_t versionM = 0, versionL = 0; am_tsplayer_init_params init_param = { .source = TS_MEMORY, .dmx_dev_id = DMX_DEV_NO, .event_mask = 0, /*AM_TSPLAYER_EVENT_TYPE_PTS_MASK | AM_TSPLAYER_EVENT_TYPE_DTV_SUBTITLE_MASK | AM_TSPLAYER_EVENT_TYPE_USERDATA_AFD_MASK | AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED_MASK | AM_TSPLAYER_EVENT_TYPE_AUDIO_CHANGED_MASK | AM_TSPLAYER_EVENT_TYPE_DATA_LOSS_MASK | AM_TSPLAYER_EVENT_TYPE_DATA_RESUME_MASK | AM_TSPLAYER_EVENT_TYPE_SCRAMBLING_MASK | AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME_MASK,*/ }; if (is_timeshifting(mode)) { init_param.dmx_dev_id = DMX_DEV_NO_2ND; } if (!tse_mode) { if (scrambled && !g_nosmp) { init_param.drmmode = TS_INPUT_BUFFER_TYPE_SECURE; } } else { if (scrambled) { init_param.drmmode = TS_INPUT_BUFFER_TYPE_TVP; } } am_tsplayer_result result = AmTsPlayer_create(init_param, &tsplayer_handle); INF( "open TsPlayer %s, result(%d)\n", (result)? "FAIL" : "OK", result); result = AmTsPlayer_setSurface(tsplayer_handle, (void *)&video_tunnel_id); INF( "set surface %s, result(%d)\n", (result)? "FAIL" : "OK", result); result = AmTsPlayer_getVersion(&versionM, &versionL); INF( "TsPlayer version(%d.%d) %s, result(%d)\n", versionM, versionL, (result)? "FAIL" : "OK", result); result = AmTsPlayer_registerCb(tsplayer_handle, tsplayer_callback, "tsp0"); INF( " AmTsPlayer_registerCb %s, result(%d)\n", (result)? "FAIL" : "OK", result); if (!tse_mode && scrambled && !g_nosmp) { AmTsPlayer_setParams(tsplayer_handle, AM_TSPLAYER_KEY_VIDEO_SECLEVEL, &seclev); AmTsPlayer_setParams(tsplayer_handle, AM_TSPLAYER_KEY_AUDIO_SECLEVEL, &seclev); CA_DEBUG(1,"%s secure level: %#x\n ", __func__, seclev); } result = AmTsPlayer_setWorkMode(tsplayer_handle, TS_PLAYER_MODE_NORMAL); INF( " TsPlayer set Workmode NORMAL %s, result(%d)\n", (result)? "FAIL" : "OK", result); //result = AmTsPlayer_setSyncMode(tsplayer_handle, TS_SYNC_NOSYNC ); //PLAY_DBG(" TsPlayer set Syncmode FREERUN %s, result(%d)", (result)? "FAIL" : "OK", result); result = AmTsPlayer_setSyncMode(tsplayer_handle, TS_SYNC_PCRMASTER ); INF( " TsPlayer set Syncmode PCRMASTER %s, result(%d)\n", (result)? "FAIL" : "OK", result); // result = AmTsPlayer_setVideoWindow(tsplayer_handle, 0, 0, 1280, 720); #ifdef ANDROID am_tsplayer_audio_patch_manage_mode audio_mode = AUDIO_PATCH_MANAGE_FORCE_ENABLE; result = AmTsPlayer_setParams(tsplayer_handle, AM_TSPLAYER_KEY_SET_AUDIO_PATCH_MANAGE_MODE, &audio_mode); INF( " TsPlayer set audio patch %s, result(%d)\n", (result)? "FAIL" : "OK", result); #endif play_params.playback_handle = (Playback_DeviceHandle_t)tsplayer_handle; play.player_session = tsplayer_handle; } play.replayed = 0; if (scrambled) { play_params.crypto_fn = decrypt_block_callback; play_params.crypto_data = NULL; } play_params.block_size = block_size; play_params.control_speed_enable = true; error = dvr_wrapper_open_playback(&player, &play_params); if (!error) { //DVR_PlaybackFlag_t play_flag = (is_timeshifting(mode))? DVR_PLAYBACK_STARTED_PAUSEDLIVE : 0; DVR_PlaybackFlag_t play_flag = (pause)? DVR_PLAYBACK_STARTED_PAUSEDLIVE : 0; play.dvr_session = (void *)player; if (!tse_mode) { if (scrambled && !g_nosmp) { INF("cas playback set secure buffer:%p, secure buffer size:%#x\n", sec_buf, sec_buf_size); dvr_wrapper_set_playback_secure_buffer(player, sec_buf, sec_buf_size); } } INF( "Starting playback\n"); error = dvr_wrapper_start_playback(player, play_flag, &play_pids); if (error) { ERR( "Start play failed, error %d\n", error); } } return 0; } static int start_tse_playback(void *params, int scrambled, int pause) { DVR_WrapperPlayback_t player = NULL; DVR_PlaybackPids_t play_pids; DVR_WrapperPlaybackOpenParams_t play_params; am_tsplayer_handle tsplayer_handle = 0; int vpid = 1024, apid = 1025, vfmt = 0, afmt = 0; int error; CA_SERVICE_TYPE_t service_type = SERVICE_PVR_PLAY; memset(&play_params, 0, sizeof(play_params)); memset(&play_pids, 0, sizeof(play_pids)); play_pids.video.type = DVR_STREAM_TYPE_VIDEO; play_pids.audio.type = DVR_STREAM_TYPE_AUDIO; if (is_timeshifting(mode)) { dvb_service_info_t *prog = (dvb_service_info_t *)params; strncpy(play_params.location, pfilename, sizeof(play_params.location)); play_params.location[sizeof(play_params.location)-1] = '\0'; play_params.is_timeshift = DVR_TRUE; play_params.dmx_dev_id = DMX_DEV_NO_2ND; vpid = prog->i_video_pid; DVR_VideoFormat_t dvb_vfmt; if (!convert_video_codec_fmt_am2dvb(prog->i_vformat, &dvb_vfmt)) { ERR("can not convert am video codec type(%d) to dtv", prog->i_vformat); } vfmt = dvb_vfmt; apid = prog->i_audio_pid; DVR_AudioFormat_t dvb_afmt; if (!convert_audio_codec_fmt_am2dvb(prog->i_aformat, &dvb_afmt)) { ERR("can not convert am audio codec type(%d) to dtv", prog->i_aformat); } afmt = dvb_afmt; service_type = SERVICE_PVR_TIMESHIFT_PLAY; } else { strncpy(play_params.location, params, sizeof(play_params.location)); play_params.location[sizeof(play_params.location)-1] = '\0'; play_params.is_timeshift = DVR_FALSE; play_params.dmx_dev_id = DMX_DEV_NO; get_dvr_info(params, &apid, &afmt, &vpid, &vfmt); } INF("vpid:%#x vfmt:%d apid:%#x afmt:%d\n", vpid, vfmt, apid, afmt); if (scrambled) { error = AM_CA_OpenSession( g_cas_handle, &play.cas_session, service_type); INF("%s open cas session:%#zx, start cas, return:%d\n", __func__, play.cas_session, error); if (error) { ERR("CAS open session failed. ret = %d\r\n", error); return -1; } AM_CA_RegisterEventCallback(play.cas_session, cas_event_cb); // dvr playback need set demux id to cas hal plugin AM_CA_PreParam_t preParam; preParam.dmx_dev = play_params.dmx_dev_id; preParam.stream_pids[0] = vpid; preParam.stream_pids[1] = apid; preParam.stream_num =2; AM_CA_DVRSetPreParam(play.cas_session, &preParam); } play_pids.video.pid = vpid; play_pids.video.format = vfmt; play_pids.audio.pid = apid; play_pids.audio.format = afmt; play_params.event_fn = PlayEventHandler; play_params.event_userdata = "play0"; /*open TsPlayer*/ { uint32_t versionM = 0, versionL = 0; am_tsplayer_init_params init_param = { .source = TS_MEMORY, .dmx_dev_id = DMX_DEV_NO, .event_mask = 0, /*AM_TSPLAYER_EVENT_TYPE_PTS_MASK | AM_TSPLAYER_EVENT_TYPE_DTV_SUBTITLE_MASK | AM_TSPLAYER_EVENT_TYPE_USERDATA_AFD_MASK | AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED_MASK | AM_TSPLAYER_EVENT_TYPE_AUDIO_CHANGED_MASK | AM_TSPLAYER_EVENT_TYPE_DATA_LOSS_MASK | AM_TSPLAYER_EVENT_TYPE_DATA_RESUME_MASK | AM_TSPLAYER_EVENT_TYPE_SCRAMBLING_MASK | AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME_MASK,*/ }; if (is_timeshifting(mode)) { init_param.dmx_dev_id = DMX_DEV_NO_2ND; } if (scrambled) { init_param.drmmode = TS_INPUT_BUFFER_TYPE_TVP; } am_tsplayer_result result = AmTsPlayer_create(init_param, &tsplayer_handle); INF( "open TsPlayer %s, result(%d)\n", (result)? "FAIL" : "OK", result); result = AmTsPlayer_setSurface(tsplayer_handle, (void *)&video_tunnel_id); INF( "set surface %s, result(%d)\n", (result)? "FAIL" : "OK", result); result = AmTsPlayer_getVersion(&versionM, &versionL); INF( "TsPlayer version(%d.%d) %s, result(%d)\n", versionM, versionL, (result)? "FAIL" : "OK", result); result = AmTsPlayer_registerCb(tsplayer_handle, tsplayer_callback, "tsp0"); INF( " AmTsPlayer_registerCb %s, result(%d)\n", (result)? "FAIL" : "OK", result); result = AmTsPlayer_setWorkMode(tsplayer_handle, TS_PLAYER_MODE_NORMAL); INF( " TsPlayer set Workmode NORMAL %s, result(%d)\n", (result)? "FAIL" : "OK", result); if (scrambled) { AmTsPlayer_setParams(tsplayer_handle, AM_TSPLAYER_KEY_VIDEO_SECLEVEL, &seclev); AmTsPlayer_setParams(tsplayer_handle, AM_TSPLAYER_KEY_AUDIO_SECLEVEL, &seclev); INF( "%s secure level: %#x\n ", __func__, seclev); CA_DEBUG(1,"%s secure level: %#x\n ", __func__, seclev); } result = AmTsPlayer_setSyncMode(tsplayer_handle, TS_SYNC_PCRMASTER ); INF( " TsPlayer set Syncmode PCRMASTER %s, result(%d)\n", (result)? "FAIL" : "OK", result); #ifdef ANDROID am_tsplayer_audio_patch_manage_mode audio_mode = AUDIO_PATCH_MANAGE_FORCE_ENABLE; result = AmTsPlayer_setParams(tsplayer_handle, AM_TSPLAYER_KEY_SET_AUDIO_PATCH_MANAGE_MODE, &audio_mode); INF( " TsPlayer set audio patch %s, result(%d)\n", (result)? "FAIL" : "OK", result); #endif play_params.playback_handle = (Playback_DeviceHandle_t)tsplayer_handle; play.player_session = tsplayer_handle; } play.replayed = 0; if (scrambled) { play_params.crypto_fn = decrypt_tse_callback; play_params.crypto_data = NULL; } play_params.block_size = block_size; play_params.control_speed_enable = true; error = dvr_wrapper_open_playback(&player, &play_params); if (!error) { //DVR_PlaybackFlag_t play_flag = (is_timeshifting(mode))? DVR_PLAYBACK_STARTED_PAUSEDLIVE : 0; DVR_PlaybackFlag_t play_flag = (pause)? DVR_PLAYBACK_STARTED_PAUSEDLIVE : 0; play_flag = play_flag | DVR_PLAYBACK_FLAG_INDEXED; play.dvr_session = (void *)player; INF( "Starting playback\n"); error = dvr_wrapper_start_playback(player, play_flag, &play_pids); if (error) { ERR( "Start play failed, error %d\n", error); } } return 0; } static int pause_playback(void) { int error = 0; if (play.dvr_session) { error = dvr_wrapper_pause_playback(play.dvr_session); } INF("pause = (%d)\n", error); return error; } static int resume_playback(void) { int error = 0; if (play.dvr_session) { error = dvr_wrapper_resume_playback(play.dvr_session); } INF("resume = (%d)\n", error); return error; } static int fast_playback(float speed) { int error = 0; if (play.dvr_session) { error = dvr_wrapper_set_playback_speed(play.dvr_session, speed); } INF("fast_speed %f = (%d)\n", speed, error); return error; } static int seek_playback(int time) { int error = 0; if (play.dvr_session) { error = dvr_wrapper_seek_playback(play.dvr_session, time); } INF("see %d = (%d)\n", time, error); return error; } static int stop_playback(void) { INF("stop_playback ==\n"); dvr_wrapper_stop_playback((DVR_WrapperPlayback_t *)play.dvr_session); if (play.cas_session) { bool tse_mode = g_indexer; AM_CA_DVRStopReplay(play.cas_session); if (!tse_mode && !g_nosmp) { AM_CA_DestroySecmem(play.cas_session, play.secmem_session); } AM_CA_CloseSession(play.cas_session); } //AmTsPlayer_stopAudioDecoding(play.player_session); //AmTsPlayer_stopVideoDecoding(play.player_session); dvr_wrapper_close_playback((DVR_WrapperPlayback_t *)play.dvr_session); AmTsPlayer_release(play.player_session); return 0; } static void usage(int argc, char *argv[]) { UNUSED(argc); INF("Usage: live : %s live \n", argv[0]); INF("Usage: local : %s local \n", argv[0]); INF("Usage: playback : %s dvrplay \n", argv[0]); INF("Usage: NOSMP=1 : S1A part don't use smp feature. need export it.\n"); INF("Usage: INDEXER=1 : Use Indexr mode in DVR.\n"); } static int cas_test_term(void) { INF("\n\n cas_test_term, mode=0x%x,has_live=%d, has_recording=%d,has_playback=%d\n", mode, has_live(mode), has_recording(mode), has_playback(mode)); if (has_live(mode)) { close_fend(g_frontend_id); stop_liveplay(); } if (has_live_local(mode)) { gInjectRunning = 0; pthread_join(gInjectThread, NULL); stop_liveplay(); } if (has_recording(mode)) { int i; INF("%s,rec_status=0x%x\n", __func__, rec_status); for (i = 0; i < MAX_REC_NUM; i++) { if (rec_status & (1 << i)) { stop_recording(i); } } } if (is_ext_playback(mode)) { ext_dvr_playback_stop(); } else if (has_playback(mode)) { stop_playback(); } if (g_cas_handle) { AM_CA_Term(g_cas_handle); } #ifdef ANDROID property_set("vendor.amtsplayer.pipeline", "1"); property_set("vendor.dtv.audio.skipamadec", "true"); #endif amsysfs_set_sysfs_str(TSN_PATH, TSN_DVB); return 0; } int amsysfs_set_sysfs_str(const char *path, const char *val) { int fd; int bytes; fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644); if (fd >= 0) { bytes = write(fd, val, strlen(val)); close(fd); return 0; } else { INF("open path:%s failed, err:%s", path, strerror(errno)); return -1; } } static void handle_signal(int signal) { UNUSED(signal); cas_test_term(); exit(0); } static void init_signal_handler() { struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = handle_signal; sigaction(SIGINT, &act, NULL); } int main(int argc, char *argv[]) { int ret; char cmd[256]; char tspath[256] = {0}; int dvr_dev_no = 0; int fend_dev_no = 0; int sym = 5217; int input_dev_no = 0; int prog_idx = 0; int scrambled = 1; int freqM = 394; int isIPTV = 0; dvb_service_info_t *prog = NULL; char *secdvr = getenv("SECDVR"); int secure_dvr = 0; char *nosmp = getenv("NOSMP"); g_nosmp = 0; char *indexer = getenv("INDEXER"); g_indexer = 0; if (secdvr) { secure_dvr = atoi(secdvr); if (secure_dvr) { INF("enable secure dvr for FTA stream\n"); } } if (nosmp) { g_nosmp = atoi(nosmp); if (g_nosmp) { INF("Env command config No smp part such as S1A T6d etc.\n"); pfilename = "/mnt/pvrdisk/timeshifting.ts"; } } else { #ifdef NOSMP_SUPPORTED g_nosmp = 1; INF("No smp part is found such as S1A T6d etc.\n"); #endif } if (indexer) { g_indexer = atoi(indexer); if (g_indexer) { INF("enable indexer mode\n"); } } if (argc < 3) { usage(argc, argv); exit(0); } init_signal_handler(); memset(&play, 0, sizeof(CasTestSession)); memset(recorder, 0, sizeof(CasTestSession)*MAX_REC_NUM); amsysfs_set_sysfs_str(TSN_PATH, TSN_DVB); char axis_buf[40]; sprintf(axis_buf, "%d %d %d %d", 0, 0, 0, 0); amsysfs_set_sysfs_str(VIDEO_AXIS_PATH, axis_buf); if (strcmp(argv[1], "live") == 0) { mode = LIVE; sscanf(argv[2], "%d", &fend_dev_no); if (argc > 3) { sscanf(argv[3], "%d", &input_dev_no); } if (argc > 4) { sscanf(argv[4], "%d", &prog_idx); } if (argc > 5) { sscanf(argv[5], "%d", &freqM); } if (argc > 6) { sscanf(argv[6], "%d", &isIPTV); } if (argc > 7) { sscanf(argv[7], "%d", &sym); } } else if (strcmp(argv[1], "local") == 0) { mode = LIVE_LOCAL; strncpy(tspath, argv[2],256); tspath[255] = '\0'; sscanf(argv[3], "%d", &prog_idx); amsysfs_set_sysfs_str(TSN_PATH, TSN_IPTV); } else if (strcmp(argv[1], "dvrrecord") == 0) { strncpy(tspath, argv[2],256); tspath[255] = '\0'; mode = RECORDING; } else if (strcmp(argv[1], "dvrplay") == 0) { int ret; struct stat buf; strncpy(tspath, argv[2],256); tspath[255] = '\0'; if (argc > 3) { sscanf(argv[3], "%d", &scrambled); } amsysfs_set_sysfs_str(TSN_PATH, TSN_IPTV); ret = stat(tspath, &buf); INF("@@@in dvrplay argc=%d, argv[3]=%s scrambled=%d,ret =%d,errno=%d\n", argc, argv[3], scrambled, ret, errno); if (ret == -1 && errno == ENOENT) { //aml dvr file path mode = PLAYBACK; } else { //external dvr file path mode = EXT_PLAYBACK; } } else { usage(argc, argv); exit(0); } INF("@@@in cas_hal_test mode = 0x%x\n", mode); if (0 == dvr_check_dmx_isNew()) { sprintf(cmd, "echo 1 > /sys/class/stb/demux_reset_all_flag"); system(cmd); inject_length = X2_INJECT_LENGTH; block_size = X2_BLOCK_SIZE; } ret = dvb_init(); set_cas_mode(g_indexer); int max_try = 5; if (!ret) { while (max_try-- > 0) { if (!show_cardno()) { break; } sleep(1); }; } if (is_live(mode) || is_live_local(mode)) { if (is_live(mode)) { DVB_DemuxSource_t dmx_src; dmx_src = DVB_DEMUX_SOURCE_TS0_1 + input_dev_no; if (dmx_src > DVB_DEMUX_SOURCE_TS7_1) { dmx_src = DVB_DEMUX_SOURCE_TS0_1; } dvb_set_demux_source(DMX_DEV_NO, dmx_src); ret = fend_lock(fend_dev_no, freqM, sym); if (ret) { INF("@@@fend_lock failed and exit with %d\n", ret); cas_test_term(); exit(0); } } else { dvb_service_info_t prog; dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_DMA0); memset(&prog, 0, sizeof(prog)); #if 0 prog.i_video_pid = 0x22; prog.i_vformat = 2; prog.i_audio_pid = 0x21; prog.i_aformat = 2; #else prog.i_video_pid = 0x1fff; prog.i_audio_pid = 0x1fff; #endif init_tsplayer_inject(&prog); gInjectRunning = 1; pthread_create(&gInjectThread, NULL, inject_thread, &tspath[0]); } int pmt_num = aml_scan(); INF("%d programs scanned\r\n", pmt_num); if (is_live_local(mode)) { gInjectRunning = 0; pthread_join(gInjectThread, NULL); stop_liveplay(); } gInjectRunning = 0; prog = aml_get_program(prog_idx); INF("try to play program:%d handle:%#zx, secure_dvr=%d,prog->scrambled=%d\r\n", prog_idx, (size_t)prog, secure_dvr, prog->scrambled); if (prog && is_live(mode)) { if (secure_dvr) { prog->scrambled = 1; } if (isIPTV) { prog->service_type = IPTV_TYPE; } else { prog->service_type = DVB_TYPE; } start_descrambling(prog); start_liveplay(prog); } else if (prog && is_live_local(mode)) { start_descrambling(prog); init_tsplayer_inject(prog); gInjectRunning = 1; pthread_create(&gInjectThread, NULL, inject_thread, &tspath[0]); } #if 0 //for test pattern else { dvb_service_info_t prog; prog.i_audio_pid = 0x1fff; prog.i_video_pid = 0x80; prog.i_vformat = 2; start_liveplay(&prog); start_descrambling(&prog); INF("invalid prog_idx:%x \r\n", prog_idx); } #endif } else if (is_playback(mode)) { INF("try to play file:%s scrambled:%d pause:0\r\n", tspath, scrambled); dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_DMA0); if (g_indexer) { ret = start_tse_playback(tspath, scrambled, 0); } else { ret = start_playback(tspath, scrambled, 0); } if (ret) { INF("@@@start_playback failed and exit with %d\n", ret); cas_test_term(); exit(0); } } else if (is_ext_playback(mode)) { INF("try to play file:%s\r\n", tspath); dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_DMA0); ret = ext_dvr_playback(tspath, g_cas_handle); if (ret) { INF("@@@ext_dvr_playback failed and exit with %d\n", ret); cas_test_term(); exit(0); } } sprintf(cmd, "mount -t debugfs debugfs /sys/kernel/debug"); system(cmd); sprintf(cmd, "echo 1 > /sys/kernel/debug/dri/0/vpu/blank"); system(cmd); sprintf(cmd, "echo 1 > /sys/class/graphics/fb0/osd_display_debug"); system(cmd); sprintf(cmd, "echo 1 > /sys/class/graphics/fb0/blank"); system(cmd); sprintf(cmd, "echo 1 > /sys/class/graphics/fb1/blank"); system(cmd); sprintf(cmd, " echo 1 > /sys/kernel/debug/dri/0/vpu/blank"); system(cmd); sprintf(cmd, "echo 0 2 > /sys/class/video/path_select"); system(cmd); sprintf(cmd, "echo 1 > /sys/class/video/video_global_output"); system(cmd); sprintf(cmd, "echo 0 > /sys/class/video/disable_video"); system(cmd); while ( running ) { char buf[256]; memset( buf, 0 , 256 ); INF( "********************\n" ); INF( "* commands:\n" ); INF( "* dvrrecord \n" ); INF( "* //algono: choose differ algo,\n" ); INF( "* dvrstop // dvrrecord stop\n" ); INF( "* zap //zap live channel\n" ); INF( "* tsstart // from live enter timeshift\n" ); INF( "* //algono: choose differ algo,\n" ); INF( "* tsstop // timeshift stop, enter live\n" ); INF( "* oc [ ]\n"); INF( "* pin \n"); INF( "* wm \n"); INF( "* hdcp \n"); INF( "* ta2ta \n"); INF( "* arb <0>/<1>\n"); INF( "* quit\n" ); INF( "********************\n" ); if (fgets(buf, 256, stdin)) { if (!strncmp(buf, "quit", 4)) { running = 0; } else if (!strncmp(buf, "stop", 4)) { stop_liveplay(); } else if (!strncmp(buf, "zap", 3)) { int prog_idx; ret = sscanf(buf, "zap %d", &prog_idx); if (ret >= 1) { if (has_live(mode)) { prog = aml_get_program(prog_idx); if (prog) { stop_liveplay(); start_descrambling(prog); start_liveplay(prog); } } } } else if (!strncmp(buf, "dvrrecord", 9)) { int prog_idx; uint8_t algo; DVB_DemuxSource_t dmx_src; INF("dvrrecord buf=%s\r\n", buf); isIPTV = 0; ret = sscanf(buf, "dvrrecord %d %d %255s %hhu %d", &dvr_dev_no, &prog_idx, &tspath[0], &algo, &isIPTV); INF("dvrrecord dvr_dev_no:%d,%d,%s,0x%x, %d\r\n", dvr_dev_no, prog_idx, tspath, algo, isIPTV); if (dvr_dev_no >= MAX_REC_NUM || dvr_dev_no < 0) { INF("dvrrecord dvr_dev_no is not correct value!\r\n"); continue; } if (ret >= 4) { dvr_test_config(algo); } if (ret >= 3) { #if 0 if (mode & RECORDING) { ERR("DVR already start, please stop dvr first\r\n"); continue; } if (dvr_dev_no != 0) { ERR("Now, must use DVR device0\r\n"); continue; } #endif prog = aml_get_program(prog_idx); INF("try to record program:%d handle:%#zx\r\n", prog_idx, (size_t)prog); if (prog) { if (isIPTV) { prog->service_type = IPTV_TYPE; } else { prog->service_type = DVB_TYPE; } if (secure_dvr) { prog->scrambled = 1; } //TODO: change source according by CAS encryption mode. M2M or TSE dmx_src = DVB_DEMUX_SOURCE_TS0_1 + input_dev_no; if (dmx_src > DVB_DEMUX_SOURCE_TS7_1) { dmx_src = DVB_DEMUX_SOURCE_TS0_1; } //if (prog->scrambled) { // dvr_dev_no = dvr_dev_no + 1; //} INF("try to record prog->scrambled=%d,dvr_dev_no=%d, dmx_src=%d\r\n", prog->scrambled, dvr_dev_no, dmx_src); dvb_set_demux_source(dvr_dev_no, dmx_src); if (g_indexer) { ret = start_tse_recording(dvr_dev_no, prog, tspath); } else { ret = start_recording(dvr_dev_no, prog, tspath); } if (!ret) { mode |= RECORDING; rec_status |= (1 << dvr_dev_no); INF("recording%d started\n", dvr_dev_no); } else { ERR("start recording failed. ret:%d\r\n", ret); } } else { ERR("invalid prog_idx:%x \r\n", prog_idx); } } } else if (!strncmp(buf, "dvrstop", 7)) { ret = sscanf(buf, "dvrstop %d", &dvr_dev_no); if (ret != 1) { ERR("wrong input, cmd: dvrstop dvr_dev_no"); continue; } if (dvr_dev_no >= MAX_REC_NUM || dvr_dev_no < 0) { INF("dvrrecord dvr_dev_no is not correct value!\r\n"); continue; } rec_status &= ~(1 << dvr_dev_no); if (rec_status == 0) { mode &= ~RECORDING; } if (g_indexer) { ret = stop_tse_recording(dvr_dev_no); }else { ret = stop_recording(dvr_dev_no); } if (!ret) { INF("recording%d stopped\n", dvr_dev_no); } else { INF("recording%d stop failed:%d\n", dvr_dev_no, ret); } } else if (!strncmp(buf, "tsstart", 7)) { if (has_recording(mode)) { ERR("DVR already start, please stop dvr first\n"); continue; } if (is_live(mode)) { uint8_t algo; stop_liveplay(); mode = TIMESHIFTING; strncpy(tspath, pfilename,256); tspath[255] = '\0'; ret = sscanf(buf, "tsstart %hhu", &algo); if (ret >= 1) { dvr_test_config(algo); } dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_TS0 + input_dev_no); if (g_indexer) { ret = start_tse_recording(DVR_DEV_NO, prog, tspath); } else { ret = start_recording(DVR_DEV_NO, prog, tspath); } if (!ret) { rec_status |= (1 << DVR_DEV_NO); INF("recording-%d started\n", DVR_DEV_NO); } else { INF("recording-%d failed. return.\n", DVR_DEV_NO); rec_status &= (1 << DVR_DEV_NO); stop_playback(); if (g_indexer) { ret = stop_tse_recording(DVR_DEV_NO); }else { ret = stop_recording(DVR_DEV_NO); } INF("recording%d stopped, ret: %d\n", DVR_DEV_NO,ret); mode = LIVE; dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_TS0_1 + input_dev_no); start_descrambling(prog); start_liveplay(prog); continue; } INF("timeshift%d before play\n", dvr_dev_no); //amsysfs_set_sysfs_str(TSN_PATH, TSN_IPTV); usleep(2000000); INF("timeshift%d begin play\n", dvr_dev_no); dvb_set_demux_source(DMX_DEV_NO_2ND, DVB_DEMUX_SOURCE_DMA1); if (g_indexer) { ret = start_tse_playback(prog, prog->scrambled, 0); } else { ret = start_playback(prog, prog->scrambled, 0); } if (ret) { INF("@@@start_playback failed and exit with %d\n", ret); rec_status &= (1 << DVR_DEV_NO); stop_playback(); if (g_indexer) { ret = stop_tse_recording(DVR_DEV_NO); }else { ret = stop_recording(DVR_DEV_NO); } INF("recording%d stopped, ret: %d\n", DVR_DEV_NO,ret); mode = LIVE; dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_TS0_1 + input_dev_no); start_descrambling(prog); start_liveplay(prog); continue; } } else { ERR("Not in live only mode, cannot enter timeshift\n"); } } else if (!strncmp(buf, "tsstop", 6)) { if (is_timeshifting(mode)) { rec_status &= (1 << DVR_DEV_NO); stop_playback(); if (g_indexer) { ret = stop_tse_recording(DVR_DEV_NO); }else { ret = stop_recording(DVR_DEV_NO); } INF("recording%d stopped, ret: %d\n", DVR_DEV_NO,ret); mode = LIVE; dvb_set_demux_source(DMX_DEV_NO, DVB_DEMUX_SOURCE_TS0_1 + input_dev_no); start_descrambling(prog); start_liveplay(prog); } else { ERR("Not in timeshifint mode\n"); } } else if (!strncmp(buf, "pause", 5)) { INF("pause, has_playback(mode=%d)=%d\n", mode, has_playback(mode)); if (has_playback(mode)) { pause_playback(); } } else if (!strncmp(buf, "resume", 6)) { if (has_playback(mode)) { resume_playback(); } } else if (!strncmp(buf, "fast", 4)) { if (has_playback(mode)) { float speed = 100; ret = sscanf(buf, "fast %f ", &speed); if (ret >= 1) { fast_playback(speed); } } } else if (!strncmp(buf, "seek", 4)) { if (has_playback(mode)) { int time = 0; ret = sscanf(buf, "seek %d ", &time); if (ret >= 1) { seek_playback(time); } } } else if (!strncmp(buf, "cardno", 6)) { show_cardno(); } else if (!strncmp(buf, "boxid", 5)) { show_boxid(); } else if (!strncmp(buf, "wm", 2)) { uint8_t on = 0, config = 0, strength = 0; ret = sscanf(buf, "wm %hhu %hhu %hhu", &on, &config, &strength); if (ret >= 1) { g_vm_config.run = 1; g_vm_config.on = on; g_vm_config.config = config; g_vm_config.strength = strength; watermark_test_config(on, config, strength); } } else if (!strncmp(buf, "oc", 2)) { uint32_t flag = 0; uint8_t analog = 0, cgmsa = 0, emicci = 0; ret = sscanf(buf, "oc %u %hhu %hhu %hhu", &flag, &analog, &cgmsa, &emicci); if (ret >= 1) { g_oc_config.run = 1; g_oc_config.flag = flag; g_oc_config.analog = analog; g_oc_config.cgmsa = cgmsa; g_oc_config.emicci = emicci; output_control_test_config(flag, analog, cgmsa, emicci); } } else if (!strncmp(buf, "pin", 3)) { uint8_t pinIndex, reason, dvrChannel; char pin[64]; dvrChannel = 255; ret = sscanf(buf, "pin %s %hhu %hhu %hhu", pin, &pinIndex, &reason, &dvrChannel); if (ret >= 3) { check_pin(pin, pinIndex, reason, dvrChannel); } } else if (!strncmp(buf, "svp", 3)) { size_t addr; ret = sscanf(buf, "svp 0x%x", &addr); if (ret == 1) { svp_test_config(addr); } } else if (!strncmp(buf, "arb", 3)) { uint8_t flag; ret = sscanf(buf, "arb %hhu", &flag); if (ret == 1) { antirollback_test_config(flag); } } else if (!strncmp(buf, "ta2ta", 5)) { char *data = (char*)malloc(2048); if (data == NULL) { ERR("malloc error!\n"); continue; } uint32_t len = 0; uint32_t clientid; uint32_t i; if (buf[5] != '\0' && buf[6] != '\0' && buf[7] != '\0' && buf[8]!= '\0') { sscanf(buf, "ta2ta %u", &clientid); strncpy(data, buf + 8, 2048); data[2047] = '\0'; len = strlen(data); INF("sending len=%u data=", len); for (i = 0; i < len && i < 256; i++) { INF("%02x ", data[i]); } INF("\n"); ta2ta_test_config(clientid, data, len); INF("received data="); for (i = 0; i < len && i < 256; i++) { INF("%02x ", data[i]); } INF("\n"); } if (data) free(data); } else if (!strncmp(buf, "hdcp", 4)) { uint8_t svc_idx = 0; sscanf(buf, "hdcp %hhu", &svc_idx); hdcp_test_config(svc_idx); } } }; cas_test_term(); exit(0); }