blob: e8a6f860bb4ca2a9f0f455b6c82d19fbc39d39d3 [file] [log] [blame]
/*
* Copyright (c) 2020 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <fstream>
#include <unistd.h>
#include <sys/time.h>
#include <cstdlib>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <thread>
#include <atomic>
#include <map>
#include <mutex>
#include <queue>
#include <thread>
#include <condition_variable>
#include <chrono>
#include <sys/time.h>
#include <memory>
#include <getopt.h>
#include <chrono>
#include "AmTsPlayer.h"
//#include <conio.h>
#include <stdio.h>
#include <sys/select.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <iostream>
using namespace std;
const int kRwSize = 188*1024;
const int kRwTimeout = 500;
#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif
#define NO_AUDIO 1
void video_callback(void *user_data, am_tsplayer_event *event)
{
if (!event) {
return ;
}
UNUSED(user_data);
printf("video_callback type %d\n", event->type);
switch (event->type) {
case AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED:
{
printf("[evt] AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED: %d x %d @%d [%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_USERDATA_AFD:
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;
printf("[evt] USERDATA [%d] : %x-%x-%x-%x %x-%x-%x-%x ,size %d\n",
event->type, pbuf[0], pbuf[1], pbuf[2], pbuf[3],
pbuf[4], pbuf[5], pbuf[6], pbuf[7], size);
UNUSED(pbuf);
UNUSED(size);
break;
}
case AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME:
{
printf("[evt] AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME\n");
break;
}
case AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_VIDEO:
{
printf("[evt] AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_VIDEO\n");
break;
}
case AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_AUDIO:
{
printf("[evt] AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_AUDIO\n");
break;
}
case AM_TSPLAYER_EVENT_TYPE_AV_SYNC_DONE:
{
printf("[evt] AM_TSPLAYER_EVENT_TYPE_AV_SYNC_DONE\n");
break;
}
default:
break;
}
}
static int set_osd_blank(int blank)
{
const char *path1 = "/sys/class/graphics/fb0/blank";
const char *path3 = "/sys/class/graphics/fb0/osd_display_debug";
int fd;
char cmd[128] = {0};
fd = open(path3,O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd >= 0)
{
sprintf(cmd,"%d",1);
write (fd,cmd,strlen(cmd));
close(fd);
}
fd = open(path1,O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd >= 0)
{
sprintf(cmd,"%d",blank);
write (fd,cmd,strlen(cmd));
close(fd);
}
return 0;
}
static 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;
}
return -1;
}
static int set_dmx_source(int32_t dmxDevId,int32_t dmxSourceType)
{
char demux[5];
sprintf(demux,"dmx%d",dmxDevId);
amsysfs_set_sysfs_str("/sys/class/stb/source", demux);
switch (dmxSourceType) {
case 0:
amsysfs_set_sysfs_str("/sys/class/stb/demux0_source", "ts0");
break;
case 1:
amsysfs_set_sysfs_str("/sys/class/stb/demux0_source", "ts1");
break;
case 2:
amsysfs_set_sysfs_str("/sys/class/stb/demux0_source", "ts2");
break;
case 3:
amsysfs_set_sysfs_str("/sys/class/stb/demux0_source", "hiu");
break;
default:
amsysfs_set_sysfs_str("/sys/class/stb/demux0_source", "hiu");
break;
}
return 0;
}
am_tsplayer_handle session;
void signHandler(int iSignNo)
{
UNUSED(iSignNo);
AmTsPlayer_stopVideoDecoding(session);
AmTsPlayer_stopAudioDecoding(session);
AmTsPlayer_release(session);
set_osd_blank(0);
printf("signHandler:%d\n",iSignNo);
signal(SIGINT, SIG_DFL);
raise(SIGINT);
}
static void usage(char **argv)
{
printf("Usage: %s\n", argv[0]);
printf("Version 0.1\n");
printf("[options]:\n");
printf("-i | --in Ts file path\n");
printf("-t | --tstype TS1:0,TS1:1,TS2:2,HIU:3[default]\n");
printf("-d | --dmxDevId demux0:0[default],demux1:1,demux2:2\n");
printf("-y | --avsync amaster:0[default], vmaster:1, pcrmaster:2, nosync:3\n");
printf("-c | --vtrick none:0[default], pause:1, pause next:2, Ionly:3\n");
printf("-v | --vcodec unknown:0, mpeg1:1, mpeg2:2, h264:3[default], h265:4, vp9:5 avs:6 mpeg4:7\n");
printf("-a | --acodec unknown:0, mp2:1, mp3:2, ac3:3, eac3:4, dts:5, aac:6[default], latm:7, pcm:8\n");
printf("-V | --vpid video pid, default 0x100\n");
printf("-A | --apid audio pid, default 0x101\n");
printf("-g | --gain audio volume, default 20\n");
printf("-o | --adpid ad pid, default -1\n");
printf("-p | --adtype ad acodec, default -1\n");
printf("-q | --admixlevel ad mixlevel, default 50\n");
printf("-h | --help print this usage\n");
}
using namespace std;
int _kbhit() {
static const int STDIN = 0;
static bool initialized = false;
if (!initialized) {
// Use termios to turn off line buffering
termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initialized = true;
}
int bytesWaiting;
ioctl(STDIN, FIONREAD, &bytesWaiting);
return bytesWaiting;
}
int main(int argc, char **argv)
{
int optionChar = 0;
int optionIndex = 0;
const char *shortOptions = "i:t:d:b:y:c:v:a:V:A:g:o:p:q:h";
struct option longOptions[] = {
{ "in", required_argument, NULL, 'i' },
{ "tstype", required_argument, NULL, 't' },
{ "dmxDevId", required_argument, NULL, 'd' },
{ "buftype", required_argument, NULL, 'b' },
{ "avsync", required_argument, NULL, 'y' },
{ "videotrick", required_argument, NULL, 'c' },
{ "vcodec", required_argument, NULL, 'v' },
{ "acodec", required_argument, NULL, 'a' },
{ "vpid", required_argument, NULL, 'V' },
{ "apid", required_argument, NULL, 'A' },
{ "gain", required_argument, NULL, 'g' },
{ "adpid", required_argument, NULL, 'o' },
{ "adtype", required_argument, NULL, 'p' },
{ "admixlevel", required_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ NULL, 0, NULL, 0 },
};
std::string inputTsName("/data/1.ts");
am_tsplayer_input_source_type tsType = TS_MEMORY;
am_tsplayer_input_buffer_type drmmode = TS_INPUT_BUFFER_TYPE_NORMAL;
am_tsplayer_avsync_mode avsyncMode= TS_SYNC_AMASTER;
am_tsplayer_video_trick_mode vTrickMode = AV_VIDEO_TRICK_MODE_NONE;
am_tsplayer_video_codec vCodec = AV_VIDEO_CODEC_H264;
am_tsplayer_audio_codec aCodec = AV_AUDIO_CODEC_AAC;
int32_t vPid = 0x100;
int32_t aPid = 0x101;
int32_t dmxSourceType = 3;
int32_t dmxDevId = 0;
int32_t gain = 20;
int32_t adtype = -1;
int32_t adpid = -1;
int32_t admixlevel = 50;
while ((optionChar = getopt_long(argc, argv, shortOptions,
longOptions, &optionIndex)) != -1) {
switch (optionChar) {
case 'i':
inputTsName.assign((const char*)optarg);
break;
case 't':
dmxSourceType = static_cast<am_tsplayer_input_source_type>(atoi(optarg));
break;
case 'd':
dmxDevId = atoi(optarg);
break;
case 'y':
avsyncMode = static_cast<am_tsplayer_avsync_mode>(atoi(optarg));
break;
case 'c':
vTrickMode = static_cast<am_tsplayer_video_trick_mode>(atoi(optarg));
break;
case 'v':
vCodec = static_cast<am_tsplayer_video_codec>(atoi(optarg));
break;
case 'a':
aCodec = static_cast<am_tsplayer_audio_codec>(atoi(optarg));
break;
case 'V':
vPid = atoi(optarg);
break;
case 'A':
aPid = atoi(optarg);
break;
case 'g':
gain = atoi(optarg);
break;
case 'o':
adpid = atoi(optarg);
break;
case 'p':
adtype = atoi(optarg);
break;
case 'q':
admixlevel = atoi(optarg);
break;
case 'h':
usage(argv);
exit(-1);
default:
break;
}
}
if (dmxSourceType >= 0 && dmxSourceType <= 2) {
tsType = TS_DEMOD;
} else {
tsType = TS_MEMORY;
}
signal(SIGINT, signHandler);
set_osd_blank(1);
char* buf = new char[kRwSize];
uint64_t fsize = 0;
ifstream file(inputTsName.c_str(), ifstream::binary);
set_dmx_source(dmxDevId,dmxSourceType);
if (tsType) {
file.seekg(0, file.end);
fsize = file.tellg();
if (fsize <= 0) {
printf("file %s size %lld return\n", inputTsName.c_str(), fsize);
return 0;
}
file.seekg(0, file.beg);
}
printf("file name = %s, is_open %d, size %lld, tsType %d\n",
inputTsName.c_str(), file.is_open(), fsize, tsType);
//am_tsplayer_handle session;
am_tsplayer_init_params parm = {tsType, drmmode, 0, 0};
AmTsPlayer_create(parm, &session);
int tunnelid = 0;
AmTsPlayer_setSurface(session,(void*)&tunnelid);
uint32_t versionM, versionL;
AmTsPlayer_getVersion(&versionM, &versionL);
uint32_t instanceno;
AmTsPlayer_getInstansNo(session, &instanceno);
AmTsPlayer_setWorkMode(session, TS_PLAYER_MODE_NORMAL);
AmTsPlayer_registerCb(session, video_callback, NULL);
#if NO_AUDIO
AmTsPlayer_setSyncMode(session, avsyncMode);
#endif
am_tsplayer_video_params vparm;
vparm.codectype = vCodec;
vparm.pid = vPid;
if (tsType == TS_DEMOD) {
AmTsPlayer_setPcrPid(session,vPid);
}
AmTsPlayer_setVideoParams(session, &vparm);
AmTsPlayer_startVideoDecoding(session);
#if NO_AUDIO
if (adpid != -1 && adtype != -1 && tsType == TS_DEMOD) {
am_tsplayer_audio_params adparm;
adparm.codectype = static_cast<am_tsplayer_audio_codec>(adtype);
adparm.pid = adpid;
AmTsPlayer_setADParams(session,&adparm);
AmTsPlayer_enableADMix(session);
//master_vol no use,just set slave_vol
AmTsPlayer_setADMixLevel(session, 0, admixlevel);
} else {
AmTsPlayer_disableADMix(session);
}
am_tsplayer_audio_params aparm;
aparm.codectype = aCodec;
aparm.pid = aPid;
AmTsPlayer_setAudioParams(session, &aparm);
AmTsPlayer_startAudioDecoding(session);
AmTsPlayer_setAudioVolume(session, gain);
#endif
AmTsPlayer_showVideo(session);
AmTsPlayer_setTrickMode(session, vTrickMode);
bool bExitManual = false;
am_tsplayer_input_buffer ibuf = {TS_INPUT_BUFFER_TYPE_NORMAL, (char*)buf, 0};
long pos = 0;
int ch = 0;
if (tsType) {
while (1) {
if (file.eof()) {
printf("file read eof\n");
break;
}
file.read(buf, (int)kRwSize);
ibuf.buf_size = kRwSize;
pos += kRwSize;
int retry = 100;
am_tsplayer_result res;
do {
if (_kbhit()) {
ch = getchar();
if (ch == 113) {
printf("====>break by q \n");
bExitManual = true;
break;
}
if (ch == 'p') {
printf("====> stop video when writedata \n");
AmTsPlayer_stopVideoDecoding(session);
}
if (ch == 'r') {
am_tsplayer_video_params vparm;
vparm.codectype = vCodec;
vparm.pid = vPid;
printf("====> start video when writedata \n");
AmTsPlayer_setVideoParams(session, &vparm);
AmTsPlayer_startVideoDecoding(session);
}
if (ch == 'a') {
printf("====> stop audio when writedata \n");
AmTsPlayer_stopAudioDecoding(session);
}
if (ch == 's') {
printf("====> start audio when writedata \n");
am_tsplayer_audio_params aparm;
aparm.codectype = aCodec;
aparm.pid = aPid;
AmTsPlayer_setAudioParams(session, &aparm);
AmTsPlayer_startAudioDecoding(session);
}
}
res = AmTsPlayer_writeData(session, &ibuf, kRwTimeout);
//usleep(20000);
if (res == AM_TSPLAYER_ERROR_RETRY) {
usleep(50000);
} else
break;
} while(res || retry-- > 0);
if (bExitManual == true) {
printf("====>break by bExitManual \n");
break;
}
if (_kbhit()) {
ch = getchar();
printf("----key input : %d quit:q\n",ch);
if (ch == 113) {
printf("----break\n");
break;
}
if (ch == 'p') {
printf("====>stop video \n");
AmTsPlayer_stopVideoDecoding(session);
}
if (ch == 'r') {
am_tsplayer_video_params vparm;
vparm.codectype = vCodec;
vparm.pid = vPid;
printf("====>start video \n");
AmTsPlayer_setVideoParams(session, &vparm);
AmTsPlayer_startVideoDecoding(session);
}
if (ch == 'a') {
printf("====> stop audio \n");
AmTsPlayer_stopAudioDecoding(session);
}
if (ch == 's') {
printf("====> start audio \n");
am_tsplayer_audio_params aparm;
aparm.codectype = aCodec;
aparm.pid = aPid;
AmTsPlayer_setAudioParams(session, &aparm);
AmTsPlayer_startAudioDecoding(session);
}
}
}
if (ch != 113)
std::this_thread::sleep_for(std::chrono::seconds(10));
} else {
while (1) {
if (_kbhit()) {
ch = getchar();
printf("----key input : %d quit:q\n",ch);
if (ch == 113) {
printf("----break\n");
break;
}
} else {
usleep(10000);
}
}
}
if (buf) {
delete [](buf);
buf = NULL;
}
if (file.is_open())
file.close();
set_osd_blank(0);
AmTsPlayer_stopVideoDecoding(session);
AmTsPlayer_stopAudioDecoding(session);
AmTsPlayer_release(session);
printf("exit\n");
return 0;
}