blob: f9679ce449777265548eab7f8445eb46233fbda2 [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 <termios.h>
#include <sys/select.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <iostream>
using namespace std;
#define ONLY_ONE_VIDEO 0
#if ONLY_ONE_VIDEO
const int changNum = 1;
#else
const int changNum = 2;
#endif
am_tsplayer_handle g_session[changNum] = {0};
typedef struct {
char tsFilePatch[50];
am_tsplayer_video_codec videoFmt;
am_tsplayer_audio_codec audioFmt;
int vpid;
int apid;
am_tsplayer_input_source_type inPutTsType;
am_tsplayer_input_buffer_type drmmode;
int index;
bool run;
bool mute;
bool setAudio;
pthread_t mThread;
} TsParams;
void video_callback(void *user_data, am_tsplayer_event *event)
{
if (!event || !user_data) {
return ;
}
TsParams* mTsParams = (TsParams*)user_data;
printf("video_callback type %d\n", event->type);
switch (event->type) {
case AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED:
{
printf("index:%d [evt] AM_TSPLAYER_EVENT_TYPE_VIDEO_CHANGED: %d x %d @%d [%d]\n",
mTsParams->index,
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("index:%d [evt] USERDATA [%d] : %x-%x-%x-%x %x-%x-%x-%x ,size %d\n",
mTsParams->index,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("index:%d [evt] AM_TSPLAYER_EVENT_TYPE_FIRST_FRAME\n",mTsParams->index);
break;
}
case AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_VIDEO:
{
printf("index:%d [evt] AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_VIDEO\n",mTsParams->index);
break;
}
case AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_AUDIO:
{
printf("index:%d [evt] AM_TSPLAYER_EVENT_TYPE_DECODE_FIRST_FRAME_AUDIO\n",mTsParams->index);
break;
}
case AM_TSPLAYER_EVENT_TYPE_AV_SYNC_DONE:
{
printf("index:%d [evt] AM_TSPLAYER_EVENT_TYPE_AV_SYNC_DONE\n",mTsParams->index);
break;
}
case AM_TSPLAYER_EVENT_TYPE_INPUT_VIDEO_BUFFER_DONE:
{
// printf("[evt] AM_TSPLAYER_EVENT_TYPE_INPUT_VIDEO_BUFFER_DONE,%p\n",event->event.ptr);
break;
}
case AM_TSPLAYER_EVENT_TYPE_INPUT_AUDIO_BUFFER_DONE:
{
// printf("[evt] AM_TSPLAYER_EVENT_TYPE_INPUT_AUDIO_BUFFER_DONE\n");
break;
}
default:
break;
}
}
void* TsPlayerThread(void *arg) {
TsParams* mTsParams = (TsParams*)arg;
mTsParams->run = true;
std::string inputTsName(mTsParams->tsFilePatch);
am_tsplayer_handle session;
am_tsplayer_avsync_mode avsyncMode= TS_SYNC_AMASTER;
am_tsplayer_video_trick_mode vTrickMode = AV_VIDEO_TRICK_MODE_NONE;
int kRwSize = 188*300;
int kRwTimeout = 30000;
char buf[kRwSize];
long long fsize = 0;
ifstream file(inputTsName.c_str(), ifstream::binary);
if (mTsParams->inPutTsType == TS_MEMORY) {
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("inde:%d file name = %s is_open %d, size %lld, inPutTsType %d drmmode:%d \n",
mTsParams->index,
inputTsName.c_str(),
file.is_open(),
fsize,
mTsParams->inPutTsType,
mTsParams->drmmode);
int x = 0, y = 0, w = 0, h = 0;
int tunnelid = 0;
switch (mTsParams->index) {
case 0:
tunnelid = 0;
x = 0;
y = 0;
w = 960;
h = 540;
break;
case 1:
tunnelid = 1;
x = 960;
y = 0;
w = 960;
h = 540;
break;
case 2:
tunnelid = 2;
x = 0;
y = 540;
w = 960;
h = 540;
break;
case 3:
tunnelid = 3;
x = 960;
y = 540;
w = 960;
h = 540;
break;
default:
break;
}
am_tsplayer_init_params parm = {mTsParams->inPutTsType, mTsParams->drmmode, mTsParams->index, 0};
AmTsPlayer_create(parm, &session);
if (mTsParams->index < changNum) {
g_session[mTsParams->index] = session;
}
AmTsPlayer_setSurface(session,(void*)&tunnelid);
AmTsPlayer_setVideoWindow(session, x, y, w, h);
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, (void*)mTsParams);
AmTsPlayer_setSyncMode(session, avsyncMode);
am_tsplayer_video_params vparm;
vparm.codectype = mTsParams->videoFmt;
vparm.pid = mTsParams->vpid;
AmTsPlayer_setVideoParams(session, &vparm);
AmTsPlayer_startVideoDecoding(session);
am_tsplayer_audio_params aparm;
aparm.codectype = mTsParams->audioFmt;
aparm.pid = mTsParams->apid;
AmTsPlayer_setAudioMute(session,false,mTsParams->mute);
AmTsPlayer_setAudioParams(session, &aparm);
AmTsPlayer_startAudioDecoding(session);
AmTsPlayer_showVideo(session);
AmTsPlayer_setTrickMode(session, vTrickMode);
am_tsplayer_input_buffer ibuf = {TS_INPUT_BUFFER_TYPE_NORMAL, (char*)buf, 0};
am_tsplayer_result res;
while (mTsParams->inPutTsType)
{
if (file.eof()) {
printf("file read eof index:%d\n",mTsParams->index);
break;
}
file.read(buf, (int)kRwSize);
ibuf.buf_size = kRwSize;
int retry = 100;
do {
if (!mTsParams->run) {
printf("break by quit******index:%d \n",mTsParams->index);
break;
}
res = AmTsPlayer_writeData(session, &ibuf, kRwTimeout);
if (res == AM_TSPLAYER_ERROR_RETRY ) {
usleep(300000);
} else {
break;
}
} while(res || retry-- > 0);
if (!mTsParams->run) {
break;
}
}
while (mTsParams->inPutTsType == TS_DEMOD &&
mTsParams->run) {
usleep(1000000);
}
mTsParams->run = false;
printf("AmTsPlayer_stopVideoDecoding index:%d\n",mTsParams->index);
AmTsPlayer_stopVideoDecoding(session);
AmTsPlayer_stopAudioDecoding(session);
printf("AmTsPlayer_release index:%d\n",mTsParams->index);
AmTsPlayer_release(session);
printf("AmTsPlayer_release ok index:%d\n",mTsParams->index);
return NULL;
}
void signHandler(int iSignNo) {
(void) iSignNo;
return;
}
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;
}
#if ONLY_ONE_VIDEO
void changAudio(TsParams* mTsParams,int number) {
bool bSetMute = false;
bSetMute = (number == 0) ? false : true;
if (mTsParams[0].mute != bSetMute) {
mTsParams[0].mute = bSetMute;
mTsParams[0].setAudio = true;
AmTsPlayer_setAudioMute(g_session[0],false,mTsParams[0].mute);
printf("AmTsPlayer_setAudioMute : %d \n",mTsParams[0].mute);
}
return;
}
#else
void changAudio(TsParams* mTsParams,int number) {
for (int i = 0 ; i < changNum;i++) {
if (mTsParams[i].mute == false) {
if (i == number) {
return;
} else {
mTsParams[i].mute = true;
mTsParams[i].setAudio = true;
AmTsPlayer_setAudioMute(g_session[i],false,mTsParams[i].mute);
printf("index:%d AmTsPlayer_setAudioMute : %d \n",i,mTsParams[i].mute);
break;
}
}
}
// usleep(200000);
mTsParams[number].mute = false;
mTsParams[number].setAudio = true;
AmTsPlayer_setAudioMute(g_session[number],false,mTsParams[number].mute);
printf("index:%d AmTsPlayer_setAudioMute : %d \n",number,mTsParams[number].mute);
return;
}
#endif
void stopVideo(TsParams* mTsParams,int number) {
printf("index:%d AmTsPlayer_stopVideoDecoding \n",number);
AmTsPlayer_stopVideoDecoding(g_session[number]);
return;
}
void startVideo(TsParams* mTsParams,int number) {
am_tsplayer_video_params vparm;
vparm.codectype = mTsParams->videoFmt;
vparm.pid = mTsParams->vpid;
printf("index:%d AmTsPlayer_startVideoDecoding \n",number);
AmTsPlayer_setVideoParams(g_session[number], &vparm);
AmTsPlayer_startVideoDecoding(g_session[number]);
return;
}
void hideVideo(TsParams* mTsParams,int number) {
printf("index:%d AmTsPlayer_hideVideo \n",number);
AmTsPlayer_hideVideo(g_session[number]);
return;
}
void showVideo(TsParams* mTsParams,int number) {
printf("index:%d AmTsPlayer_showVideo \n",number);
AmTsPlayer_showVideo(g_session[number]);
return;
}
void printfStatus(TsParams* mTsParams,char ch) {
int i = 0;
printf("\n");
printf("******************************\n");
printf("******* key input : %c ********\n",ch);
printf("******** q:quit ***********\n");
for (i = 0 ; i < changNum;i++) {
printf("*******%d:%d channel sound******\n",i,i);
}
for (i = 0 ; i < changNum;i++) {
printf("*** number:%d audioMute:%d ***\n",i,mTsParams[i].mute);
}
printf("******************************\n");
}
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
signal(SIGINT, signHandler);
TsParams mTsParams[changNum];
char const* file0 = "/data/1.ts";
int file0_len = strlen(file0);
memcpy(mTsParams[0].tsFilePatch,file0,file0_len);
mTsParams[0].tsFilePatch[file0_len] = '\0';
printf("file0:%s file0_len:%d\n",file0,file0_len);
mTsParams[0].videoFmt = AV_VIDEO_CODEC_H264;
mTsParams[0].audioFmt = AV_AUDIO_CODEC_AAC;
mTsParams[0].vpid = 0x100;
mTsParams[0].apid = 0x101;
mTsParams[0].inPutTsType = TS_MEMORY;
mTsParams[0].drmmode = TS_INPUT_BUFFER_TYPE_NORMAL;
mTsParams[0].index = 0;
mTsParams[0].mThread = 0;
mTsParams[0].run = true;
mTsParams[0].mute = false;
mTsParams[0].setAudio = false;
#if !ONLY_ONE_VIDEO
char const* file1 = "/data/2.ts";
int file1_len = strlen(file1);
memcpy(mTsParams[1].tsFilePatch,file1,file1_len);
mTsParams[1].tsFilePatch[file1_len] = '\0';
mTsParams[1].videoFmt = AV_VIDEO_CODEC_H264;
mTsParams[1].audioFmt = AV_AUDIO_CODEC_MP3;
mTsParams[1].vpid = 0xc8;
mTsParams[1].apid = 0xc9;
mTsParams[1].inPutTsType = TS_MEMORY;
mTsParams[1].drmmode = TS_INPUT_BUFFER_TYPE_NORMAL;
mTsParams[1].index = 1;
mTsParams[1].mThread = 0;
mTsParams[1].run = true;
mTsParams[1].mute = true;
mTsParams[1].setAudio = false;
#endif
#if 0
char const* file2 = "/data/2.ts";
memcpy(mTsParams[2].tsFilePatch,file2,strlen(file2));
mTsParams[2].videoFmt = AV_VIDEO_CODEC_H264;
mTsParams[2].audioFmt = AV_AUDIO_CODEC_MP3;
mTsParams[2].vpid = 0xc8;
mTsParams[2].apid = 0xc9;
mTsParams[2].inPutTsType = TS_MEMORY;
mTsParams[2].drmmode = TS_INPUT_BUFFER_TYPE_NORMAL;
mTsParams[2].index = 2;
mTsParams[2].mThread = 0;
mTsParams[2].mute = true;
mTsParams[2].setAudio = false;
char const* file3 = "/data/2.ts";
memcpy(mTsParams[3].tsFilePatch,file3,strlen(file3));
mTsParams[3].videoFmt = AV_VIDEO_CODEC_H264;
mTsParams[3].audioFmt = AV_AUDIO_CODEC_MP3;
mTsParams[3].vpid = 0xc8;
mTsParams[3].apid = 0xc9;
mTsParams[3].inPutTsType = TS_MEMORY;
mTsParams[3].drmmode = TS_INPUT_BUFFER_TYPE_NORMAL;
mTsParams[3].index = 3;
mTsParams[3].mThread = 0;
mTsParams[3].run = true;
mTsParams[3].mute = true;
mTsParams[3].setAudio = false;
#endif
int i = 0;
for (i = 0 ; i < changNum;i++) {
if (pthread_create(&(mTsParams[i].mThread), NULL, TsPlayerThread, &mTsParams[i]) == 0) {
printf("pthread_create %d ok %ld\n",i,mTsParams[i].mThread);
} else {
mTsParams[i].mThread = 0;
printf("pthread_create %d errno:%d (%s) \n",i,errno,strerror(errno));
}
usleep(5000);
}
char ch = 0;
bool isExit = false;
int run_false_index_count = 0;
while (1) {
if (_kbhit()) {
ch = getchar();
printfStatus(mTsParams,ch);
switch (ch) {
case 'q':
printf("----break\n");
for (i = 0 ; i < changNum;i++) {
mTsParams[i].run = false;
}
isExit = true;
break;
case '0':
changAudio(mTsParams, 0);
break;
case '1':
changAudio(mTsParams, 1);
break;
case 'p':
//stop video 2 decoding,test
stopVideo(mTsParams,changNum-1);
break;
case 'r':
//start video 2 decoding,test
startVideo(mTsParams,changNum-1);
break;
case 'h':
printf("----hide the video 1\n");
hideVideo(mTsParams,changNum-1);
break;
case 's':
printf("----show the video 1\n");
showVideo(mTsParams,changNum-1);
break;
default:
break;
}
ch = 0;
}
run_false_index_count = 0;
for (i = 0 ; i < changNum;i++) {
if (mTsParams[i].run == false) {
run_false_index_count++;
}
}
if (run_false_index_count == changNum) {
isExit = true;
printf("---->all channel exit changNum:%d \n",changNum);
}
if (isExit) {
break;
}
usleep(200000);
}
for (i = 0 ; i < changNum;i++) {
printf("---->pthread_join %d \n",i);
mTsParams[i].run = false;
if (mTsParams[i].mThread != 0) {
pthread_join(mTsParams[i].mThread, NULL);
mTsParams[i].mThread = 0;
}
}
printf("---->pthread_join end\n");
return 0;
}