mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2025-07-01 23:35:47 +00:00
Merge remote-tracking branch 'areascout/rockchip'
This commit is contained in:
commit
d8d7f75ee5
@ -14,6 +14,7 @@ find_package(Opus REQUIRED)
|
||||
find_package(Broadcom)
|
||||
find_package(Freescale)
|
||||
find_package(Amlogic)
|
||||
find_package(Rockchip)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(EVDEV REQUIRED libevdev)
|
||||
@ -97,6 +98,16 @@ if(FREESCALE_FOUND)
|
||||
install(TARGETS moonlight-imx DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
if(ROCKCHIP_FOUND)
|
||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_ROCKCHIP)
|
||||
list(APPEND MOONLIGHT_OPTIONS ROCKCHIP)
|
||||
add_library(moonlight-rk SHARED ./src/video/rk.c)
|
||||
target_include_directories(moonlight-rk PRIVATE ${ROCKCHIP_INCLUDE_DIRS} ${GAMESTREAM_INCLUDE_DIR} ${MOONLIGHT_COMMON_INCLUDE_DIR})
|
||||
target_link_libraries(moonlight-rk gamestream ${ROCKCHIP_LIBRARIES})
|
||||
set_property(TARGET moonlight-rk PROPERTY COMPILE_DEFINITIONS ${ROCKCHIP_DEFINITIONS})
|
||||
install(TARGETS moonlight-rk DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
if (SOFTWARE_FOUND)
|
||||
target_sources(moonlight PRIVATE ./src/video/ffmpeg.c)
|
||||
target_include_directories(moonlight PRIVATE ${AVCODEC_INCLUDE_DIRS} ${AVUTIL_INCLUDE_DIRS})
|
||||
@ -146,12 +157,12 @@ if (PULSE_FOUND)
|
||||
target_link_libraries(moonlight ${PULSE_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR X11_FOUND)
|
||||
if (AMLOGIC_FOUND OR BROADCOM_FOUND OR FREESCALE_FOUND OR ROCKCHIP_FOUND OR X11_FOUND)
|
||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_EMBEDDED)
|
||||
list(APPEND MOONLIGHT_OPTIONS EMBEDDED)
|
||||
endif()
|
||||
|
||||
if(NOT AMLOGIC_FOUND AND NOT BROADCOM_FOUND AND NOT FREESCALE_FOUND AND NOT SOFTWARE_FOUND)
|
||||
if(NOT AMLOGIC_FOUND AND NOT BROADCOM_FOUND AND NOT FREESCALE_FOUND AND NOT ROCKCHIP_FOUND AND NOT SOFTWARE_FOUND)
|
||||
message(FATAL_ERROR "No video output available")
|
||||
endif()
|
||||
|
||||
|
29
cmake/FindRockchip.cmake
Normal file
29
cmake/FindRockchip.cmake
Normal file
@ -0,0 +1,29 @@
|
||||
find_path(DRM_INCLUDE_DIR
|
||||
NAMES drm.h
|
||||
DOC "libdrm include directory"
|
||||
PATHS /usr/local/include/libdrm /usr/include/libdrm /usr/include)
|
||||
mark_as_advanced(DRM_INCLUDE_DIR)
|
||||
|
||||
find_path(DRM_LIBRARY
|
||||
NAMES libdrm.so
|
||||
DOC "Path to libdrm Library"
|
||||
PATHS /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/arm-linux-gnueabihf)
|
||||
mark_as_advanced(DRM_INCLUDE_DIR)
|
||||
|
||||
find_path(ROCKCHIP_INCLUDE_DIR
|
||||
NAMES rk_mpi.h
|
||||
DOC "Rockchip include directory"
|
||||
PATHS /usr/local/include/rockchip /usr/include/rockchip /usr/include)
|
||||
mark_as_advanced(ROCKCHIP_INCLUDE_DIR)
|
||||
|
||||
find_library(ROCKCHIP_LIBRARY
|
||||
NAMES librockchip_mpp.so
|
||||
DOC "Path to Rockchip Media Process Platform Library"
|
||||
PATHS /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/arm-linux-gnueabihf)
|
||||
mark_as_advanced(ROCKCHIP_LIBRARY)
|
||||
|
||||
include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Rockchip DEFAULT_MSG ROCKCHIP_INCLUDE_DIR ROCKCHIP_LIBRARY)
|
||||
|
||||
set(ROCKCHIP_INCLUDE_DIRS ${ROCKCHIP_INCLUDE_DIR} ${DRM_INCLUDE_DIR})
|
||||
set(ROCKCHIP_LIBRARIES ${ROCKCHIP_LIBRARY} ${DRM_LIBRARY})
|
@ -46,6 +46,7 @@
|
||||
## Select the audio and video decoder to use
|
||||
## default - autodetect
|
||||
## aml - hardware video decoder for ODROID-C1/C2
|
||||
## rk - hardware video decoder for ODROID-N1 Rockchip
|
||||
## omx - hardware video decoder for Raspberry Pi
|
||||
## imx - hardware video decoder for i.MX6 devices
|
||||
## x11 - software decoder
|
||||
|
@ -172,7 +172,7 @@ static void help() {
|
||||
printf("\t-surround\t\tStream 5.1 surround sound (requires GFE 2.7)\n");
|
||||
printf("\t-keydir <directory>\tLoad encryption keys from directory\n");
|
||||
printf("\t-mapping <file>\t\tUse <file> as gamepad mappings configuration file\n");
|
||||
printf("\t-platform <system>\tSpecify system used for audio, video and input: pi/imx/aml/x11/x11_vdpau/sdl/fake (default auto)\n");
|
||||
printf("\t-platform <system>\tSpecify system used for audio, video and input: pi/imx/aml/rk/x11/x11_vdpau/sdl/fake (default auto)\n");
|
||||
printf("\t-unsupported\t\tTry streaming if GFE version or options are unsupported\n");
|
||||
#if defined(HAVE_SDL) || defined(HAVE_X11)
|
||||
printf("\n WM options (SDL and X11 only)\n\n");
|
||||
|
@ -59,6 +59,13 @@ enum platform platform_check(char* name) {
|
||||
return AML;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ROCKCHIP
|
||||
if (std || strcmp(name, "rk") == 0) {
|
||||
void *handle = dlopen("libmoonlight-rk.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
if (handle != NULL && dlsym(RTLD_DEFAULT, "mpp_init") != NULL)
|
||||
return RK;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
bool x11 = strcmp(name, "x11") == 0;
|
||||
bool vdpau = strcmp(name, "x11_vdpau") == 0;
|
||||
@ -148,6 +155,10 @@ DECODER_RENDERER_CALLBACKS* platform_get_video(enum platform system) {
|
||||
case AML:
|
||||
return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_aml");
|
||||
#endif
|
||||
#ifdef HAVE_ROCKCHIP
|
||||
case RK:
|
||||
return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_rk");
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -178,6 +189,7 @@ AUDIO_RENDERER_CALLBACKS* platform_get_audio(enum platform system, char* audio_d
|
||||
bool platform_supports_hevc(enum platform system) {
|
||||
switch (system) {
|
||||
case AML:
|
||||
case RK:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -191,6 +203,8 @@ char* platform_name(enum platform system) {
|
||||
return "i.MX6 (MXC Vivante)";
|
||||
case AML:
|
||||
return "AMLogic VPU";
|
||||
case RK:
|
||||
return "Rockchip VPU";
|
||||
case X11:
|
||||
return "X Window System (software decoding)";
|
||||
case X11_VAAPI:
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#define IS_EMBEDDED(SYSTEM) SYSTEM != SDL
|
||||
|
||||
enum platform { NONE, SDL, X11, X11_VDPAU, X11_VAAPI, PI, IMX, AML, FAKE };
|
||||
enum platform { NONE, SDL, X11, X11_VDPAU, X11_VAAPI, PI, IMX, AML, RK, FAKE };
|
||||
|
||||
enum platform platform_check(char*);
|
||||
PDECODER_RENDERER_CALLBACKS platform_get_video(enum platform system);
|
||||
|
484
src/video/rk.c
Normal file
484
src/video/rk.c
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015-2018 Iwan Timmer
|
||||
* Copyright (C) 2018 Martin Cerveny, Daniel Mehrwald
|
||||
*
|
||||
* Moonlight is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Moonlight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Moonlight; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Limelight.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
#include <rockchip/rk_mpi.h>
|
||||
|
||||
#define READ_BUF_SIZE (SZ_1M)
|
||||
#define MAX_FRAMES 16
|
||||
#define RK_H264 7
|
||||
#define RK_H265 16777220
|
||||
|
||||
void *pkt_buf = NULL;
|
||||
int fd;
|
||||
int fb_id;
|
||||
uint32_t plane_id, crtc_id;
|
||||
int frm_eos;
|
||||
int crtc_width;
|
||||
int crtc_height;
|
||||
RK_U32 frm_width;
|
||||
RK_U32 frm_height;
|
||||
int fb_x, fb_y, fb_width, fb_height;
|
||||
|
||||
pthread_t tid_frame, tid_display;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
drmModePlane *ovr = NULL;
|
||||
drmModeEncoder *encoder = NULL;
|
||||
drmModeConnector *connector = NULL;
|
||||
drmModeRes *resources = NULL;
|
||||
drmModePlaneRes *plane_resources = NULL;
|
||||
drmModeCrtcPtr crtc = {0};
|
||||
|
||||
MppCtx mpi_ctx;
|
||||
MppApi *mpi_api;
|
||||
MppPacket mpi_packet;
|
||||
MppBufferGroup mpi_frm_grp;
|
||||
|
||||
struct {
|
||||
int prime_fd;
|
||||
int fb_id;
|
||||
uint32_t handle;
|
||||
} frame_to_drm[MAX_FRAMES];
|
||||
|
||||
void *display_thread(void *param) {
|
||||
|
||||
int ret;
|
||||
|
||||
while (!frm_eos) {
|
||||
int _fb_id;
|
||||
|
||||
ret = pthread_mutex_lock(&mutex);
|
||||
assert(!ret);
|
||||
while (fb_id == 0) {
|
||||
pthread_cond_wait(&cond, &mutex);
|
||||
assert(!ret);
|
||||
if (fb_id == 0 && frm_eos) {
|
||||
ret = pthread_mutex_unlock(&mutex);
|
||||
assert(!ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
_fb_id = fb_id;
|
||||
|
||||
fb_id = 0;
|
||||
ret = pthread_mutex_unlock(&mutex);
|
||||
assert(!ret);
|
||||
|
||||
// show DRM FB in overlay plane (auto vsynced/atomic !)
|
||||
ret = drmModeSetPlane(fd, plane_id, crtc_id, _fb_id, 0,
|
||||
fb_x, fb_y, fb_width, fb_height,
|
||||
0, 0, frm_width << 16, frm_height << 16);
|
||||
assert(!ret);
|
||||
}
|
||||
}
|
||||
|
||||
void *frame_thread(void *param) {
|
||||
|
||||
int count = 0;
|
||||
int ret;
|
||||
int i;
|
||||
MppFrame frame = NULL;
|
||||
|
||||
while (!frm_eos) {
|
||||
|
||||
ret = mpi_api->decode_get_frame(mpi_ctx, &frame);
|
||||
if (ret != MPP_OK && ret != MPP_ERR_TIMEOUT) {
|
||||
if (count < 3) {
|
||||
fprintf(stderr, "Waiting for Frame (return code = %d, retry count = %d)\n", ret, count);
|
||||
usleep(10000);
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (frame) {
|
||||
if (mpp_frame_get_info_change(frame)) {
|
||||
// new resolution
|
||||
assert(!mpi_frm_grp);
|
||||
|
||||
frm_width = mpp_frame_get_width(frame);
|
||||
frm_height = mpp_frame_get_height(frame);
|
||||
RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
|
||||
RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
|
||||
MppFrameFormat fmt = mpp_frame_get_fmt(frame);
|
||||
assert((fmt == MPP_FMT_YUV420SP) || (fmt == MPP_FMT_YUV420SP_10BIT));
|
||||
|
||||
// position overlay, scale to ratio
|
||||
float crt_ratio = (float)crtc_width/crtc_height;
|
||||
float frame_ratio = (float)frm_width/frm_height;
|
||||
|
||||
if (crt_ratio>frame_ratio) {
|
||||
fb_width = frame_ratio/crt_ratio*crtc_width;
|
||||
fb_height = crtc_height;
|
||||
fb_x = (crtc_width-fb_width)/2;
|
||||
fb_y = 0;
|
||||
} else {
|
||||
fb_width = crtc_width;
|
||||
fb_height = crt_ratio/frame_ratio*crtc_height;
|
||||
fb_x = 0;
|
||||
fb_y = (crtc_height-fb_height)/2;
|
||||
}
|
||||
|
||||
// create new external frame group and allocate (commit flow) new DRM buffers and DRM FB
|
||||
assert(!mpi_frm_grp);
|
||||
ret = mpp_buffer_group_get_external(&mpi_frm_grp, MPP_BUFFER_TYPE_DRM);
|
||||
assert(!ret);
|
||||
for (i = 0; i < MAX_FRAMES; i++) {
|
||||
|
||||
// new DRM buffer
|
||||
struct drm_mode_create_dumb dmcd = {0};
|
||||
dmcd.bpp = fmt == MPP_FMT_YUV420SP ? 8:10;
|
||||
dmcd.width = hor_stride;
|
||||
dmcd.height = ver_stride * 2; // documentation say not v*2/3 but v*2 (additional info included)
|
||||
do {
|
||||
ret = ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcd);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
assert(!ret);
|
||||
assert(dmcd.pitch == (fmt == MPP_FMT_YUV420SP?hor_stride:hor_stride * 10 / 8));
|
||||
assert(dmcd.size == (fmt == MPP_FMT_YUV420SP?hor_stride:hor_stride * 10 / 8) * ver_stride * 2);
|
||||
frame_to_drm[i].handle = dmcd.handle;
|
||||
|
||||
// commit DRM buffer to frame group
|
||||
struct drm_prime_handle dph = {0};
|
||||
dph.handle = dmcd.handle;
|
||||
dph.fd = -1;
|
||||
do {
|
||||
ret = ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
assert(!ret);
|
||||
MppBufferInfo info = {0};
|
||||
info.type = MPP_BUFFER_TYPE_DRM;
|
||||
info.size = dmcd.width * dmcd.height;
|
||||
info.fd = dph.fd;
|
||||
ret = mpp_buffer_commit(mpi_frm_grp, &info);
|
||||
assert(!ret);
|
||||
frame_to_drm[i].prime_fd = info.fd; // dups fd
|
||||
|
||||
// allocate DRM FB from DRM buffer
|
||||
uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
|
||||
handles[0] = frame_to_drm[i].handle;
|
||||
offsets[0] = 0;
|
||||
pitches[0] = hor_stride;
|
||||
handles[1] = frame_to_drm[i].handle;
|
||||
offsets[1] = hor_stride * ver_stride;
|
||||
pitches[1] = hor_stride;
|
||||
ret = drmModeAddFB2(fd, frm_width, frm_height, fmt == MPP_FMT_YUV420SP ? DRM_FORMAT_NV12:DRM_FORMAT_NV12_10, handles, pitches, offsets, &frame_to_drm[i].fb_id, 0);
|
||||
assert(!ret);
|
||||
}
|
||||
// register external frame group
|
||||
ret = mpi_api->control(mpi_ctx, MPP_DEC_SET_EXT_BUF_GROUP, mpi_frm_grp);
|
||||
ret = mpi_api->control(mpi_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
|
||||
|
||||
} else {
|
||||
// regular frame received
|
||||
|
||||
MppBuffer buffer = mpp_frame_get_buffer(frame);
|
||||
if (buffer) {
|
||||
// find fb_id by frame prime_fd
|
||||
MppBufferInfo info;
|
||||
ret = mpp_buffer_info_get(buffer, &info);
|
||||
assert(!ret);
|
||||
for (i = 0; i < MAX_FRAMES; i++) {
|
||||
if (frame_to_drm[i].prime_fd == info.fd) break;
|
||||
}
|
||||
assert(i != MAX_FRAMES);
|
||||
// send DRM FB to display thread
|
||||
ret = pthread_mutex_lock(&mutex);
|
||||
assert(!ret);
|
||||
fb_id = frame_to_drm[i].fb_id;
|
||||
ret = pthread_cond_signal(&cond);
|
||||
assert(!ret);
|
||||
ret = pthread_mutex_unlock(&mutex);
|
||||
assert(!ret);
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Frame no buff\n");
|
||||
}
|
||||
}
|
||||
|
||||
frm_eos = mpp_frame_get_eos(frame);
|
||||
mpp_frame_deinit(&frame);
|
||||
frame = NULL;
|
||||
} else {
|
||||
if (!frm_eos) {
|
||||
fprintf(stderr, "Didn't get frame from MPP (return code = %d)\n", ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rk_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
int format = 0;
|
||||
|
||||
switch (videoFormat) {
|
||||
case VIDEO_FORMAT_H264:
|
||||
format = RK_H264;
|
||||
break;
|
||||
case VIDEO_FORMAT_H265:
|
||||
format = RK_H265;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Video format not supported\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MppCodingType mpp_type = (MppCodingType)format;
|
||||
ret = mpp_check_support_format(MPP_CTX_DEC, mpp_type);
|
||||
assert(!ret);
|
||||
|
||||
fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
|
||||
assert(fd >= 0);
|
||||
|
||||
resources = drmModeGetResources(fd);
|
||||
assert(resources);
|
||||
|
||||
// find active monitor
|
||||
for (i = 0; i < resources->count_connectors; ++i) {
|
||||
connector = drmModeGetConnector(fd, resources->connectors[i]);
|
||||
if (!connector) {
|
||||
continue;
|
||||
}
|
||||
if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) {
|
||||
break;
|
||||
}
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
assert(i < resources->count_connectors);
|
||||
|
||||
for (i = 0; i < resources->count_encoders; ++i) {
|
||||
encoder = drmModeGetEncoder(fd, resources->encoders[i]);
|
||||
if (!encoder) {
|
||||
continue;
|
||||
}
|
||||
if (encoder->encoder_id == connector->encoder_id) {
|
||||
break;
|
||||
}
|
||||
drmModeFreeEncoder(encoder);
|
||||
}
|
||||
assert(i < resources->count_encoders);
|
||||
|
||||
for (i = 0; i < resources->count_crtcs; ++i) {
|
||||
if (resources->crtcs[i] == encoder->crtc_id) {
|
||||
crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
|
||||
assert(crtc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(i < resources->count_crtcs);
|
||||
crtc_id = crtc->crtc_id;
|
||||
crtc_width = crtc->width;
|
||||
crtc_height = crtc->height;
|
||||
uint32_t crtc_bit = (1 << i);
|
||||
|
||||
ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||
assert(!ret);
|
||||
plane_resources = drmModeGetPlaneResources(fd);
|
||||
assert(plane_resources);
|
||||
|
||||
// search for OVERLAY (for active connector, unused, NV12 support)
|
||||
for (i = 0; i < plane_resources->count_planes; i++) {
|
||||
ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
|
||||
if (!ovr) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < ovr->count_formats; j++) {
|
||||
if (ovr->formats[j] == DRM_FORMAT_NV12) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == ovr->count_formats) {
|
||||
continue;
|
||||
}
|
||||
if ((ovr->possible_crtcs & crtc_bit) && !ovr->crtc_id) {
|
||||
drmModeObjectPropertiesPtr props = drmModeObjectGetProperties(fd, plane_resources->planes[i], DRM_MODE_OBJECT_PLANE);
|
||||
if (!props) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < props->count_props && !plane_id; j++) {
|
||||
drmModePropertyPtr prop = drmModeGetProperty(fd, props->props[j]);
|
||||
if (!prop) {
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(prop->name, "type") && props->prop_values[j] == DRM_PLANE_TYPE_OVERLAY) {
|
||||
plane_id = ovr->plane_id;
|
||||
}
|
||||
drmModeFreeProperty(prop);
|
||||
}
|
||||
drmModeFreeObjectProperties(props);
|
||||
if (plane_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
drmModeFreePlane(ovr);
|
||||
}
|
||||
assert(plane_id);
|
||||
|
||||
// disable cursor
|
||||
drmModeSetCursor(fd, crtc_id, 0, 0, 0);
|
||||
|
||||
// MPI SETUP
|
||||
|
||||
pkt_buf = malloc(READ_BUF_SIZE);
|
||||
assert(pkt_buf);
|
||||
ret = mpp_packet_init(&mpi_packet, pkt_buf, READ_BUF_SIZE);
|
||||
assert(!ret);
|
||||
|
||||
ret = mpp_create(&mpi_ctx, &mpi_api);
|
||||
assert(!ret);
|
||||
|
||||
// decoder split mode (multi-data-input) need to be set before init
|
||||
int param = 1;
|
||||
ret = mpi_api->control(mpi_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, ¶m);
|
||||
assert(!ret);
|
||||
|
||||
ret = mpp_init(mpi_ctx, MPP_CTX_DEC, mpp_type);
|
||||
assert(!ret);
|
||||
|
||||
// set blocked read on Frame Thread
|
||||
param = MPP_POLL_BLOCK;
|
||||
ret = mpi_api->control(mpi_ctx, MPP_SET_OUTPUT_BLOCK, ¶m);
|
||||
assert(!ret);
|
||||
|
||||
ret = pthread_mutex_init(&mutex, NULL);
|
||||
assert(!ret);
|
||||
ret = pthread_cond_init(&cond, NULL);
|
||||
assert(!ret);
|
||||
|
||||
ret = pthread_create(&tid_frame, NULL, frame_thread, NULL);
|
||||
assert(!ret);
|
||||
ret = pthread_create(&tid_display, NULL, display_thread, NULL);
|
||||
assert(!ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rk_cleanup() {
|
||||
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
frm_eos = 1;
|
||||
ret = pthread_mutex_lock(&mutex);
|
||||
assert(!ret);
|
||||
ret = pthread_cond_signal(&cond);
|
||||
assert(!ret);
|
||||
ret = pthread_mutex_unlock(&mutex);
|
||||
assert(!ret);
|
||||
|
||||
ret = pthread_join(tid_display, NULL);
|
||||
assert(!ret);
|
||||
|
||||
ret = pthread_cond_destroy(&cond);
|
||||
assert(!ret);
|
||||
ret = pthread_mutex_destroy(&mutex);
|
||||
assert(!ret);
|
||||
|
||||
ret = mpi_api->reset(mpi_ctx);
|
||||
assert(!ret);
|
||||
|
||||
ret = pthread_join(tid_frame, NULL);
|
||||
assert(!ret);
|
||||
|
||||
if (mpi_frm_grp) {
|
||||
ret = mpp_buffer_group_put(mpi_frm_grp);
|
||||
assert(!ret);
|
||||
mpi_frm_grp = NULL;
|
||||
for (i = 0; i < MAX_FRAMES; i++) {
|
||||
ret = drmModeRmFB(fd, frame_to_drm[i].fb_id);
|
||||
assert(!ret);
|
||||
struct drm_mode_destroy_dumb dmdd = {0};
|
||||
dmdd.handle = frame_to_drm[i].handle;
|
||||
do {
|
||||
ret = ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dmdd);
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
assert(!ret);
|
||||
}
|
||||
}
|
||||
|
||||
mpp_packet_deinit(&mpi_packet);
|
||||
mpp_destroy(mpi_ctx);
|
||||
free(pkt_buf);
|
||||
|
||||
drmModeFreePlane(ovr);
|
||||
drmModeFreePlaneResources(plane_resources);
|
||||
drmModeFreeEncoder(encoder);
|
||||
drmModeFreeConnector(connector);
|
||||
drmModeFreeCrtc(crtc);
|
||||
drmModeFreeResources(resources);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int rk_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
|
||||
int result = DR_OK;
|
||||
|
||||
if (decodeUnit->fullLength < READ_BUF_SIZE) {
|
||||
PLENTRY entry = decodeUnit->bufferList;
|
||||
int length = 0;
|
||||
while (entry != NULL) {
|
||||
memcpy(pkt_buf+length, entry->data, entry->length);
|
||||
length += entry->length;
|
||||
entry = entry->next;
|
||||
}
|
||||
if (length) {
|
||||
mpp_packet_set_pos(mpi_packet, pkt_buf);
|
||||
mpp_packet_set_length(mpi_packet, length);
|
||||
|
||||
while (MPP_OK != mpi_api->decode_put_packet(mpi_ctx, mpi_packet))
|
||||
;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DECODER_RENDERER_CALLBACKS decoder_callbacks_rk = {
|
||||
.setup = rk_setup,
|
||||
.cleanup = rk_cleanup,
|
||||
.submitDecodeUnit = rk_submit_decode_unit,
|
||||
.capabilities = CAPABILITY_DIRECT_SUBMIT,
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user