Files

3086 lines
99 KiB
C
Raw Permalink Normal View History

2026-08-13 11:28:40 +08:00
/**
* \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 <fend_dev_no> <input_dev_no> <prog_index> <freqM> <isIPTV>
* \endcode
* For Live local:
* \code
* cas_hal_test local <tsfile> <prog_index>
* \endcode
* For playback:
* \code
* cas_hal_test dvrplay <tsfile> <scramble_flag>
* \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 <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdbool.h>
#include <sys/time.h>
#ifdef ANDROID
#include <cutils/properties.h>
#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(&param, 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 <fend_dev_no> <input_dev_no> <prog_idx> <freqM> <isIPTV> <sym>\n", argv[0]);
INF("Usage: local : %s local <tsfile> <prog_idx>\n", argv[0]);
INF("Usage: playback : %s dvrplay <tsfile> <scramble_flag>\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 <dvr_dev_no> <prog_idx> <tspath> <algono> <isIPTV>\n" );
INF( "* //algono: choose differ algo,\n" );
INF( "* dvrstop <dvr_dev_no> // dvrrecord stop\n" );
INF( "* zap <prog_idx> //zap live channel\n" );
INF( "* tsstart <algono> // from live enter timeshift\n" );
INF( "* //algono: choose differ algo,\n" );
INF( "* tsstop // timeshift stop, enter live\n" );
INF( "* oc <value> [<AnalogProtection> <Cgmsa> <Emicci>]\n");
INF( "* pin <pin> <pinIdx> <reason> <dvr_dev_no>\n");
INF( "* wm <on> <config> <strength>\n");
INF( "* hdcp <svc_idx>\n");
INF( "* ta2ta <client id> <ascii input data>\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);
}