Files
2026-08-24 10:03:24 +08:00

3086 lines
99 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* \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);
}