216 lines
7.9 KiB
C++
216 lines
7.9 KiB
C++
/*
|
|||
|
|
* Copyright (C) 2014-2025 Amlogic, Inc. All rights reserved.
|
||
|
|
*
|
||
|
|
* All information contained herein is Amlogic confidential.
|
||
|
|
*
|
||
|
|
* This software is provided to you pursuant to Software License Agreement
|
||
|
|
* (SLA) with Amlogic Inc ("Amlogic"). This software may be used
|
||
|
|
* only in accordance with the terms of this agreement.
|
||
|
|
*
|
||
|
|
* Redistribution and use in source and binary forms, with or without
|
||
|
|
* modification is strictly prohibited without prior written permission from
|
||
|
|
* Amlogic.
|
||
|
|
*
|
||
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define LOG_TAG "SysfsVideoInfo"
|
||
|
|
|
||
|
|
#include "VideoInfo.h"
|
||
|
|
|
||
|
|
#include <errno.h>
|
||
|
|
#include <fcntl.h>
|
||
|
|
#include <memory.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <sys/stat.h>
|
||
|
|
#include <sys/types.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
|
||
|
|
#include "SubtitleLog.h"
|
||
|
|
|
||
|
|
#define VIDEO_VDEC_CORE "/sys/class/vdec/core"
|
||
|
|
#define DEFAULT_VIDEO_WIDTH 720
|
||
|
|
#define DEFAULT_VIDEO_HEIGHT 480
|
||
|
|
|
||
|
|
static inline int64_t sysfsReadInt(const char *path, int base) {
|
||
|
|
int fd;
|
||
|
|
int64_t val = 0;
|
||
|
|
char bcmd[64] = {0};
|
||
|
|
fd = ::open(path, O_RDONLY);
|
||
|
|
if (fd >= 0) {
|
||
|
|
int c = ::read(fd, bcmd, sizeof(bcmd));
|
||
|
|
if (c > 0) val = strtoll(bcmd, NULL, base);
|
||
|
|
::close(fd);
|
||
|
|
}
|
||
|
|
return val;
|
||
|
|
}
|
||
|
|
|
||
|
|
class SysfsVideoInfo : public VideoInfo {
|
||
|
|
private:
|
||
|
|
int mPreviousVideoWidth = 0;
|
||
|
|
int mPreviousVideoHeight = 0;
|
||
|
|
|
||
|
|
public:
|
||
|
|
SysfsVideoInfo() {}
|
||
|
|
virtual ~SysfsVideoInfo() {}
|
||
|
|
|
||
|
|
virtual bool isVideoWithHeightReady() {
|
||
|
|
auto ret = sysfsReadInt("/sys/class/video/frame_width", 10);
|
||
|
|
if (ret == 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
ret = sysfsReadInt("/sys/class/video/frame_height", 10);
|
||
|
|
if (ret == 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual int getVideoWidth(bool useDefaultIfFail = true, bool usePreviousIfFail = false) {
|
||
|
|
auto ret = sysfsReadInt("/sys/class/video/frame_width", 10);
|
||
|
|
if (ret == 0) {
|
||
|
|
SUBTITLE_LOGE(
|
||
|
|
"Video width is not obtained, use the last obtained value or default value "
|
||
|
|
"useDefaultIfFail:%d usePreviousIfFail:%d mPreviousVideoWidth:%d",
|
||
|
|
useDefaultIfFail, usePreviousIfFail, mPreviousVideoWidth);
|
||
|
|
if (useDefaultIfFail && !usePreviousIfFail) {
|
||
|
|
ret = DEFAULT_VIDEO_WIDTH;
|
||
|
|
} else if (usePreviousIfFail) {
|
||
|
|
return mPreviousVideoWidth == 0 ? DEFAULT_VIDEO_WIDTH : mPreviousVideoWidth;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
mPreviousVideoWidth = ret;
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual int getVideoHeight(bool useDefaultIfFail = true, bool usePreviousIfFail = false) {
|
||
|
|
auto ret = sysfsReadInt("/sys/class/video/frame_height", 10);
|
||
|
|
if (ret == 0) {
|
||
|
|
SUBTITLE_LOGE(
|
||
|
|
"Video height not obtained, use the last obtained value or default value "
|
||
|
|
"useDefaultIfFail:%d usePreviousIfFail:%d mVideoHeight:%d",
|
||
|
|
useDefaultIfFail, usePreviousIfFail, mPreviousVideoHeight);
|
||
|
|
if (useDefaultIfFail && !usePreviousIfFail) {
|
||
|
|
ret = DEFAULT_VIDEO_HEIGHT;
|
||
|
|
} else if (usePreviousIfFail) {
|
||
|
|
return mPreviousVideoHeight == 0 ? DEFAULT_VIDEO_HEIGHT : mPreviousVideoHeight;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
mPreviousVideoHeight = ret;
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* helper function to check is h264 or mpeg codec.
|
||
|
|
* CC decoder process differently in these 2 codecs
|
||
|
|
*/
|
||
|
|
virtual int getVideoFormat() {
|
||
|
|
int retry = 100; // check 200ms for parser ready
|
||
|
|
while (retry-- >= 0) {
|
||
|
|
int fd = ::open(VIDEO_VDEC_CORE, O_RDONLY);
|
||
|
|
int bytes = 0;
|
||
|
|
if (fd >= 0) {
|
||
|
|
uint8_t ubuf8[1025] = {0};
|
||
|
|
memset(ubuf8, 0, 1025);
|
||
|
|
bytes = read(fd, ubuf8, 1024);
|
||
|
|
ubuf8[1024] = 0;
|
||
|
|
SUBTITLE_LOGI("getVideoFormat ubuf8:%s", ubuf8);
|
||
|
|
if (strstr((const char *)ubuf8, "amvdec_h264" /*"vdec.h264.00"*/)) {
|
||
|
|
SUBTITLE_LOGI("H264_CC_TYPE");
|
||
|
|
close(fd);
|
||
|
|
return H264_CC_TYPE;
|
||
|
|
} else if (strstr((const char *)ubuf8, "amvdec_h265" /*"vdec.h265.00"*/)) {
|
||
|
|
SUBTITLE_LOGI("H265_CC_TYPE");
|
||
|
|
close(fd);
|
||
|
|
return H265_CC_TYPE;
|
||
|
|
} else if (strstr((const char *)ubuf8, "amvdec_mpeg12" /*"vdec.mpeg12.00"*/)) {
|
||
|
|
SUBTITLE_LOGI("MPEG_CC_TYPE");
|
||
|
|
close(fd);
|
||
|
|
return MPEG_CC_TYPE;
|
||
|
|
} else if (strstr((const char *)ubuf8, "VDEC_STATUS_CONNECTED")) {
|
||
|
|
SUBTITLE_LOGI("vdec has connect, no mpeg or h264 type, return!");
|
||
|
|
close(fd);
|
||
|
|
return INVALID_CC_TYPE;
|
||
|
|
}
|
||
|
|
|
||
|
|
close(fd);
|
||
|
|
} // else {
|
||
|
|
// SUBTITLE_LOGE("open error:%d,%s!!", errno,strerror(errno));
|
||
|
|
// }
|
||
|
|
usleep(20 * 1000);
|
||
|
|
}
|
||
|
|
|
||
|
|
return INVALID_CC_TYPE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get VideoFormat and VideoDecoderType.
|
||
|
|
virtual std::pair<VideoFormat, VideoDecoderType> getVideoInfo() {
|
||
|
|
int retry = 100; // check 200ms for parser ready
|
||
|
|
bool found = false;
|
||
|
|
VideoFormat videoFormat = INVALID_CC_TYPE;
|
||
|
|
VideoDecoderType videoDecoderType = VIDEO_DECODER_TYPE_AMSTREAM_USERDATA;
|
||
|
|
while (retry-- >= 0) {
|
||
|
|
int fd = ::open(VIDEO_VDEC_CORE, O_RDONLY);
|
||
|
|
int bytes = 0;
|
||
|
|
|
||
|
|
if (fd >= 0) {
|
||
|
|
// Get ATSC CC Video Format
|
||
|
|
uint8_t ubuf8[1025] = {0};
|
||
|
|
memset(ubuf8, 0, 1025);
|
||
|
|
bytes = read(fd, ubuf8, 1024);
|
||
|
|
ubuf8[1024] = 0;
|
||
|
|
SUBTITLE_LOGI("getVideoInfo ubuf8:%s", ubuf8);
|
||
|
|
if (strstr((const char *)ubuf8, "amvdec_h264" /*"vdec.h264.00"*/)) {
|
||
|
|
videoFormat = H264_CC_TYPE;
|
||
|
|
found = true;
|
||
|
|
} else if (strstr((const char *)ubuf8, "amvdec_h265" /*"vdec.h265.00"*/)) {
|
||
|
|
videoFormat = H265_CC_TYPE;
|
||
|
|
found = true;
|
||
|
|
} else if (strstr((const char *)ubuf8, "amvdec_mpeg12" /*"vdec.mpeg12.00"*/)) {
|
||
|
|
videoFormat = MPEG_CC_TYPE;
|
||
|
|
found = true;
|
||
|
|
} else if (strstr((const char *)ubuf8, "VDEC_STATUS_CONNECTED")) {
|
||
|
|
videoFormat = INVALID_CC_TYPE;
|
||
|
|
found = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get ATSC CC decoder type, v4l or amstream userdata
|
||
|
|
if (found) {
|
||
|
|
if (strstr((const char *)ubuf8, "_v4l" /*xxxxx_v4l*/)) {
|
||
|
|
videoDecoderType = VIDEO_DECODER_TYPE_V4L;
|
||
|
|
} else {
|
||
|
|
videoDecoderType = VIDEO_DECODER_TYPE_AMSTREAM_USERDATA;
|
||
|
|
}
|
||
|
|
close(fd);
|
||
|
|
return {videoFormat, videoDecoderType};
|
||
|
|
}
|
||
|
|
|
||
|
|
close(fd);
|
||
|
|
}
|
||
|
|
usleep(20 * 1000);
|
||
|
|
}
|
||
|
|
|
||
|
|
return {INVALID_CC_TYPE, VIDEO_DECODER_TYPE_INVALID};
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
VideoInfo *VideoInfo::mInstance = nullptr;
|
||
|
|
|
||
|
|
VideoInfo *VideoInfo::Instance() {
|
||
|
|
if (mInstance == nullptr) {
|
||
|
|
mInstance = new SysfsVideoInfo();
|
||
|
|
}
|
||
|
|
return mInstance;
|
||
|
|
}
|