302 lines
9.5 KiB
C++
302 lines
9.5 KiB
C++
/*
|
|
* Copyright (c) 2019 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:
|
|
*/
|
|
#define LOG_TAG "SubtitleTest"
|
|
|
|
#include <IpcSocket.h>
|
|
#include <RemoteData.h>
|
|
#include <binder/IPCThreadState.h>
|
|
#include <binder/ProcessState.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <pthread.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/shm.h>
|
|
#include <unistd.h>
|
|
|
|
#include "SubtitleLog.h"
|
|
#include "SubtitleNativeAPI.h"
|
|
|
|
#define DEBUG_DUMP 1
|
|
|
|
#define CC_MODE_ATV 1
|
|
#define CC_MODE_DTV 2
|
|
#define MEDIA_SYNC_DEFAULT_ID 1
|
|
|
|
std::shared_ptr<IpcSocket> mReceiver;
|
|
|
|
AmlSubtitleHnd mSubtitleHandle = nullptr;
|
|
|
|
/** Close caption's input.*/
|
|
typedef enum {
|
|
CLOSED_CAPTION_INPUT_USERDATA, /**< Input from MPEG userdata.*/
|
|
CLOSED_CAPTION_INPUT_VBI /**< Input from VBI.*/
|
|
} ClosedCaptionInput;
|
|
|
|
/** caption mode*/
|
|
typedef enum {
|
|
CLOSED_CAPTION_NONE = -1,
|
|
CLOSED_CAPTION_DEFAULT,
|
|
/*NTSC CC channels*/
|
|
CLOSED_CAPTION_CC1,
|
|
CLOSED_CAPTION_CC2,
|
|
CLOSED_CAPTION_CC3,
|
|
CLOSED_CAPTION_CC4,
|
|
CLOSED_CAPTION_TEXT1,
|
|
CLOSED_CAPTION_TEXT2,
|
|
CLOSED_CAPTION_TEXT3,
|
|
CLOSED_CAPTION_TEXT4,
|
|
/*DTVCC services*/
|
|
CLOSED_CAPTION_SERVICE1,
|
|
CLOSED_CAPTION_SERVICE2,
|
|
CLOSED_CAPTION_SERVICE3,
|
|
CLOSED_CAPTION_SERVICE4,
|
|
CLOSED_CAPTION_SERVICE5,
|
|
CLOSED_CAPTION_SERVICE6,
|
|
CLOSED_CAPTION_XDS,
|
|
CLOSED_CAPTION_DATA,
|
|
CLOSED_CAPTION_MAX
|
|
} ClosedCaptionMode;
|
|
|
|
void initSocketTestReceiver() {
|
|
if (mReceiver == nullptr) {
|
|
mReceiver = std::make_shared<IpcSocket>(false);
|
|
mReceiver->start(6666, nullptr);
|
|
}
|
|
|
|
if (!mReceiver->isvalid()) {
|
|
SUBTITLE_LOGE("Client: initRemoteLocked failed \n");
|
|
mReceiver->stop();
|
|
mReceiver->join();
|
|
mReceiver = nullptr;
|
|
return;
|
|
}
|
|
|
|
mReceiver->setEventListener([](int fd, void* self) -> int {
|
|
printf("initReceiver \n");
|
|
auto reply = [](int fd) {
|
|
std::string retStr = "1";
|
|
bool send = IpcSocket::send(fd, retStr.c_str(), retStr.size());
|
|
printf("Reply %s", (send ? "OK" : "NG"));
|
|
};
|
|
|
|
char retBuf[sizeof(RemoteData)];
|
|
if (!IpcSocket::receive(fd, retBuf, sizeof(retBuf))) {
|
|
printf("Server broken, fd= %d, remove.", fd);
|
|
return EventsTracker::RET_REMOVE;
|
|
}
|
|
|
|
RemoteData* remoteData = (RemoteData*)(retBuf);
|
|
if (remoteData == nullptr) {
|
|
SUBTITLE_LOGE("Failed to allocate memory for RemoteData");
|
|
reply(fd);
|
|
return EventsTracker::RET_CONTINUE;
|
|
}
|
|
|
|
// CC metadata info
|
|
printf(
|
|
"Client received: RemoteData_ {\n"
|
|
" int type= %d;\n"
|
|
" int width= %d;\n"
|
|
" int height = %d;\n"
|
|
" int size = %d;\n"
|
|
" bool isShow= %d;\n"
|
|
" bool isText= %d;\n"
|
|
" int x= %d;\n"
|
|
" int y= %d;\n"
|
|
" int videoWidth= %d;\n"
|
|
" int videoHeight= %d;\n"
|
|
" int objectSegmentId= %d;\n"
|
|
" int shimId= %d;\n"
|
|
" int event= %d;\n"
|
|
" int channelId= %d;\n"
|
|
" int callbackType= %x;\n"
|
|
" int available= %d;\n"
|
|
" int afd= %d;\n"
|
|
" int playerid= %d;\n"
|
|
" string lang= %s;\n"
|
|
" int what= %d;\n"
|
|
" int extra= %d;\n"
|
|
"}",
|
|
remoteData->type, remoteData->width, remoteData->height, remoteData->size,
|
|
remoteData->isShow, remoteData->isText, remoteData->x, remoteData->y,
|
|
remoteData->videoWidth, remoteData->videoHeight, remoteData->objectSegmentId,
|
|
remoteData->shimId, remoteData->event, remoteData->channelId, remoteData->callbackType,
|
|
remoteData->available, remoteData->afd, remoteData->playerid, remoteData->lang,
|
|
remoteData->what, remoteData->extra);
|
|
|
|
if (remoteData->callbackType == EVENT_ON_SUBTITLEDATA_CALLBACK ||
|
|
remoteData->callbackType == EVENT_ON_SUBTITLEAVAILABLE_CALLBACK ||
|
|
remoteData->callbackType == EVENT_ON_VIDEOAFDCHANGE_CALLBACK ||
|
|
remoteData->callbackType == EVENT_ON_MIXVIDEOEVENT_CALLBACK ||
|
|
remoteData->callbackType == EVENT_ON_SUBTITLE_DIMENSION_CALLBACK ||
|
|
remoteData->callbackType == EVENT_ON_SUBTITLE_LANGUAGE_CALLBACK ||
|
|
remoteData->callbackType == EVENT_ON_SUBTITLE_INFO_CALLBACK) {
|
|
printf("SubtitleTest No cc data. \n");
|
|
reply(fd);
|
|
return EventsTracker::RET_CONTINUE;
|
|
}
|
|
|
|
// CC json data by shared mem
|
|
int shmId = shmget(remoteData->shimId, remoteData->size, 0);
|
|
if (shmId == -1) {
|
|
printf("Error get shm ipc_id error shmid=%d, error=%s \n", shmId, strerror(errno));
|
|
return EventsTracker::RET_CONTINUE;
|
|
}
|
|
|
|
char* data = (char*)shmat(shmId, NULL, 0);
|
|
|
|
#if DEBUG_DUMP
|
|
if (remoteData->isText) {
|
|
printf("cc json data: %s \n", data);
|
|
}
|
|
#endif
|
|
|
|
printf("initReceiver shmdt shmctl \n");
|
|
shmdt(data);
|
|
|
|
reply(fd);
|
|
return EventsTracker::RET_CONTINUE;
|
|
});
|
|
|
|
std::string retStr = "recv-ready";
|
|
retStr = mReceiver->sendForResult(mReceiver->fd(), retStr.c_str(), retStr.size());
|
|
printf("recv-ready result: %s \n", retStr.c_str());
|
|
if (retStr == "1") {
|
|
printf("recv-ready register OK \n");
|
|
}
|
|
}
|
|
|
|
static void startAtvCc(int channel) {
|
|
if (channel > CLOSED_CAPTION_TEXT4 || channel < CLOSED_CAPTION_CC1) {
|
|
printf("invalid cc channel:%d", channel);
|
|
}
|
|
printf("startAtvCc channel:%d", channel);
|
|
|
|
int ch = channel | CLOSED_CAPTION_INPUT_VBI << 8;
|
|
|
|
if (mSubtitleHandle == nullptr) {
|
|
mSubtitleHandle = amlsub_Create();
|
|
}
|
|
|
|
if (mSubtitleHandle == nullptr) {
|
|
printf("mSubtitleHandle is NULL");
|
|
return;
|
|
}
|
|
|
|
AmlSubtitleParam subParam{};
|
|
subParam.subtitleType = TYPE_SUBTITLE_CLOSED_CAPTION;
|
|
subParam.channelId = ch;
|
|
|
|
amlsub_Open(mSubtitleHandle, &subParam);
|
|
// amlsub_SetPip(mSubtitleHandle, MODE_SUBTITLE_PIP_MEDIASYNC, 1);
|
|
printf("amlsub_Open ok");
|
|
}
|
|
|
|
static void startDtvCc(int channel) {
|
|
int mediaSyncId = MEDIA_SYNC_DEFAULT_ID;
|
|
printf("startDtvCc ch:%x", channel);
|
|
|
|
if (mSubtitleHandle == nullptr) {
|
|
mSubtitleHandle = amlsub_Create();
|
|
}
|
|
|
|
if (mSubtitleHandle == nullptr) {
|
|
printf("mSubtitleHandle is NULL");
|
|
return;
|
|
}
|
|
|
|
AmlSubtitleParam subParam{};
|
|
subParam.subtitleType = TYPE_SUBTITLE_CLOSED_CAPTION;
|
|
subParam.channelId = channel;
|
|
|
|
amlsub_Open(mSubtitleHandle, &subParam);
|
|
amlsub_SetPip(mSubtitleHandle, MODE_SUBTITLE_PIP_MEDIASYNC, mediaSyncId);
|
|
printf("amlsub_Open ok");
|
|
}
|
|
|
|
static const char* kShortOption = "hsm:c:";
|
|
static const struct option kLongOption[] = {{"help", no_argument, 0, 'h'},
|
|
{"socktest", no_argument, 0, 's'},
|
|
{"ccMode", required_argument, NULL, 'm'},
|
|
{"channel", required_argument, NULL, 'c'},
|
|
{0, 0, 0, 0}};
|
|
|
|
static void print_usage() {
|
|
printf(
|
|
"Usage: subtitle test\n"
|
|
"Options:\n"
|
|
" -h \t list all cmd\n"
|
|
" -s \t socket test\n"
|
|
" -m \t cc mode\n"
|
|
" \t 1: CC_MODE_ATV \n"
|
|
" \t 2: CC_MODE_DTV \n"
|
|
" -c \t cc channel\n"
|
|
" \t 1: CLOSED_CAPTION_CC1 \n"
|
|
" \t 2: CLOSED_CAPTION_CC2 \n"
|
|
" \t 3: CLOSED_CAPTION_CC3 \n"
|
|
" \t 4: CLOSED_CAPTION_CC4 \n"
|
|
" \t 9: CLOSED_CAPTION_CS1 \n"
|
|
" \t10: CLOSED_CAPTION_CS2 \n"
|
|
" \t11: CLOSED_CAPTION_CS3 \n"
|
|
" \t12: CLOSED_CAPTION_CS4 \n"
|
|
" \t13: CLOSED_CAPTION_CS5 \n"
|
|
" \t14: CLOSED_CAPTION_CS6 \n"
|
|
|
|
);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc == 1) {
|
|
print_usage();
|
|
return 0;
|
|
}
|
|
|
|
int opt;
|
|
int ccMode;
|
|
int ccChannel;
|
|
while ((opt = getopt_long_only(argc, argv, kShortOption, kLongOption, NULL)) != -1) {
|
|
switch (opt) {
|
|
case 'h':
|
|
print_usage();
|
|
break;
|
|
case 's':
|
|
/*test socket cc json data*/
|
|
initSocketTestReceiver();
|
|
break;
|
|
case 'm': {
|
|
char* endptr;
|
|
ccMode = strtol(optarg, &endptr, 10);
|
|
} break;
|
|
case 'c': {
|
|
char* endptr;
|
|
ccChannel = strtol(optarg, &endptr, 10);
|
|
printf("ccMode:%d, ccChannel:%d\n", ccMode, ccChannel);
|
|
if (ccMode == CC_MODE_ATV) {
|
|
startAtvCc(ccChannel);
|
|
} else if (ccMode == CC_MODE_DTV) {
|
|
startDtvCc(ccChannel);
|
|
} else {
|
|
printf("please input ccMode first!\n");
|
|
}
|
|
} break;
|
|
default:
|
|
print_usage();
|
|
break;
|
|
}
|
|
}
|
|
|
|
while (1) continue;
|
|
printf("Process exit!");
|
|
return 0;
|
|
}
|