Add: Amlogic hardware video decoder backend

This commit is contained in:
Daniel Mehrwald
2016-03-13 11:09:59 -04:00
committed by Iwan Timmer
parent 3943ba8cd8
commit c1f5a2a30e
10 changed files with 225 additions and 6 deletions

View File

@@ -63,6 +63,9 @@ static struct option long_options[] = {
{"surround", no_argument, NULL, 'u'},
{"fps", required_argument, NULL, 'v'},
{"forcehw", no_argument, NULL, 'w'},
#ifdef HAVE_AML
{"hevc", no_argument, NULL, 'x'},
#endif
{0, 0, 0, 0},
};
@@ -199,6 +202,12 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) {
break;
case 'w':
config->forcehw = true;
break;
#ifdef HAVE_AML
case 'x':
config->hevc = true;
break;
#endif
case 1:
if (config->action == NULL)
config->action = value;
@@ -289,6 +298,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) {
config->sops = true;
config->localaudio = false;
config->fullscreen = true;
config->hevc = false;
config->inputsCount = 0;
config->mapping = get_path("mappings/default.conf", getenv("XDG_DATA_DIRS"));
@@ -306,7 +316,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) {
} else {
int option_index = 0;
int c;
while ((c = getopt_long_only(argc, argv, "-abc:d:efg:h:i:j:k:lm:no:p:q:r:stuv:w", long_options, &option_index)) != -1) {
while ((c = getopt_long_only(argc, argv, "-abc:d:efg:h:i:j:k:lm:no:p:q:r:stuv:w:x", long_options, &option_index)) != -1) {
parse_argument(c, optarg, config);
}
}

View File

@@ -43,6 +43,9 @@ typedef struct _CONFIGURATION {
bool forcehw;
struct input_config inputs[MAX_INPUTS];
int inputsCount;
#ifdef HAVE_AML
bool hevc;
#endif
} CONFIGURATION, *PCONFIGURATION;
bool inputAdded;

View File

@@ -83,6 +83,11 @@ static void stream(PSERVER_DATA server, PCONFIGURATION config, enum platform sys
exit(-1);
}
// h265
if (config->hevc) {
config->stream.supportsHevc = 1;
}
int ret = gs_start_app(server, &config->stream, appId, config->sops, config->localaudio);
if (ret < 0) {
if (ret == GS_NOT_SUPPORTED_4K)
@@ -154,6 +159,10 @@ static void help() {
printf("\t-audio <device>\t\tUse <device> as ALSA audio output device (default sysdefault)\n");
printf("\t-forcehw \t\tTry to use video hardware acceleration\n");
#endif
#ifdef HAVE_AML
printf("\n Amlogic Codec options\n\n");
printf("\t-hevc \t\tUse high efficiency video decoding (HEVC)\n");
#endif
printf("\nUse Ctrl+Alt+Shift+Q to exit streaming session\n\n");
exit(0);
}

View File

@@ -52,6 +52,10 @@ enum platform platform_check(char* name) {
if (std || strcmp(name, "sdl") == 0)
return SDL;
#endif
#ifdef HAVE_AML
if (std || strcmp(name, "aml") == 0)
return AML;
#endif
#ifdef HAVE_FAKE
if (std || strcmp(name, "fake") == 0)
return FAKE;
@@ -73,6 +77,10 @@ DECODER_RENDERER_CALLBACKS* platform_get_video(enum platform system) {
case PI:
return (PDECODER_RENDERER_CALLBACKS) dlsym(RTLD_DEFAULT, "decoder_callbacks_pi");
#endif
#ifdef HAVE_AML
case AML:
return &decoder_callbacks_aml;
#endif
#ifdef HAVE_FAKE
case FAKE:
return &decoder_callbacks_fake;

View File

@@ -25,12 +25,15 @@
#define IS_EMBEDDED(SYSTEM) SYSTEM != SDL
enum platform { NONE, SDL, PI, IMX, FAKE };
enum platform { NONE, SDL, PI, IMX, AML, FAKE };
enum platform platform_check(char*);
PDECODER_RENDERER_CALLBACKS platform_get_video(enum platform system);
PAUDIO_RENDERER_CALLBACKS platform_get_audio(enum platform system);
#ifdef HAVE_AML
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_aml;
#endif
#ifdef HAVE_FAKE
extern DECODER_RENDERER_CALLBACKS decoder_callbacks_fake;
#endif

138
src/video/aml.c Normal file
View File

@@ -0,0 +1,138 @@
/*
* This file is part of Moonlight Embedded.
*
* Copyright (C) 2015 Iwan Timmer
* Copyright (C) 2016 OtherCrashOverride, 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-common/Limelight.h"
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <amcodec/codec.h>
static codec_para_t codecParam = { 0 };
const size_t EXTERNAL_PTS = (1);
const size_t SYNC_OUTSIDE = (2);
int osd_blank(char *path,int cmd) {
int fd;
char bcmd[16];
fd = open(path, O_CREAT|O_RDWR | O_TRUNC, 0644);
if(fd>=0) {
sprintf(bcmd,"%d",cmd);
if (write(fd,bcmd,strlen(bcmd)) < 0) {
printf("osd_blank error during write.\n");
}
close(fd);
return 0;
}
return -1;
}
void init_display() {
osd_blank("/sys/class/graphics/fb0/blank",1);
osd_blank("/sys/class/graphics/fb1/blank",0);
}
void restore_display() {
osd_blank("/sys/class/graphics/fb0/blank",0);
osd_blank("/sys/class/graphics/fb1/blank",0);
}
void aml_setup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags) {
fprintf(stderr, "\nvideoFormat=%d nwidth=%d, height=%d, redrawRate=%d, context=%p, drFlags=%x\n",
videoFormat, width, height, redrawRate, context, drFlags);
init_display();
codecParam.stream_type = STREAM_TYPE_ES_VIDEO;
codecParam.has_video = 1;
codecParam.noblock = 0;
switch (videoFormat) {
case VIDEO_FORMAT_H264: // 1
if (width > 1920 || height > 1080) {
codecParam.video_type = VFORMAT_H264_4K2K;
codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_H264_4K2K; ///< video format, such as H264, MPEG2...
} else {
codecParam.video_type = VFORMAT_H264;
codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; ///< video format, such as H264, MPEG2...
}
fprintf(stdout, "Decoding H264 video.\n");
break;
case VIDEO_FORMAT_H265: // 2
codecParam.video_type = VFORMAT_HEVC;
codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_HEVC; ///< video format, such as H264, MPEG2...
fprintf(stdout, "Decoding HEVC video.\n");
break;
default:
printf("Unsupported video format.\n");
exit(1);
}
codecParam.am_sysinfo.width = width; //< video source width
codecParam.am_sysinfo.height = height; //< video source height
codecParam.am_sysinfo.rate = (96000 / (redrawRate)); //< video source frame duration
codecParam.am_sysinfo.param = (void *)(EXTERNAL_PTS | SYNC_OUTSIDE); //< other parameters for video decoder
int api = codec_init(&codecParam);
fprintf(stdout, "codec_init=%x\n", api);
if (api != 0) {
fprintf(stderr, "codec_init failed.\n");
exit(1);
}
}
void aml_cleanup() {
int api = codec_close(&codecParam);
restore_display();
}
int aml_submit_decode_unit(PDECODE_UNIT decodeUnit) {
int result = DR_OK;
PLENTRY entry = decodeUnit->bufferList;
while (entry != NULL) {
int api = codec_write(&codecParam, entry->data, entry->length);
if (api != entry->length) {
fprintf(stderr, "codec_write error: %x\n", api);
codec_reset(&codecParam);
result = DR_NEED_IDR;
break;
}
entry = entry->next;
}
return result;
}
DECODER_RENDERER_CALLBACKS decoder_callbacks_aml = {
.setup = aml_setup,
.cleanup = aml_cleanup,
.submitDecodeUnit = aml_submit_decode_unit,
.capabilities = CAPABILITY_DIRECT_SUBMIT | CAPABILITY_SLICES_PER_FRAME(8),
};