mirror of
https://github.com/moonlight-stream/moonlight-embedded.git
synced 2025-07-03 08:15:34 +00:00
Port Android SPS fixes to libgamestream
This commit is contained in:
parent
721b7561c7
commit
d5cbd7f69e
@ -41,7 +41,6 @@ endif()
|
||||
|
||||
if(BROADCOM_FOUND)
|
||||
aux_source_directory(./third_party/ilclient SRC_LIST)
|
||||
aux_source_directory(./third_party/h264bitstream SRC_LIST)
|
||||
list(APPEND SRC_LIST ./src/video/omx.c)
|
||||
list(APPEND MOONLIGHT_DEFINITIONS HAVE_OMX)
|
||||
endif()
|
||||
@ -75,7 +74,7 @@ if (CEC_FOUND)
|
||||
endif()
|
||||
|
||||
if(BROADCOM_FOUND)
|
||||
target_include_directories(moonlight PRIVATE ./third_party/ilclient ./third_party/h264bitstream ${BROADCOM_INCLUDE_DIRS})
|
||||
target_include_directories(moonlight PRIVATE ./third_party/ilclient ${BROADCOM_INCLUDE_DIRS})
|
||||
target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
|
||||
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
|
||||
endif()
|
||||
|
@ -6,6 +6,7 @@ find_package(EXPAT REQUIRED)
|
||||
pkg_check_modules(AVAHI REQUIRED avahi-client)
|
||||
|
||||
aux_source_directory(./ GAMESTREAM_SRC_LIST)
|
||||
aux_source_directory(../third_party/h264bitstream GAMESTREAM_SRC_LIST)
|
||||
|
||||
aux_source_directory(../third_party/moonlight-common-c/limelight-common MOONLIGHT_COMMON_SRC_LIST)
|
||||
aux_source_directory(../third_party/moonlight-common-c/limelight-common/OpenAES MOONLIGHT_COMMON_SRC_LIST)
|
||||
@ -19,7 +20,7 @@ target_link_libraries(gamestream LINK_PUBLIC moonlight-common)
|
||||
set_target_properties(gamestream PROPERTIES SOVERSION 0 VERSION ${MOONLIGHT_VERSION})
|
||||
set_target_properties(moonlight-common PROPERTIES SOVERSION 0 VERSION ${MOONLIGHT_VERSION})
|
||||
|
||||
target_include_directories(gamestream PRIVATE ../third_party/moonlight-common-c ${AVAHI_INCLUDE_DIRS})
|
||||
target_include_directories(gamestream PRIVATE ../third_party/moonlight-common-c ../third_party/h264bitstream ${AVAHI_INCLUDE_DIRS})
|
||||
target_link_libraries (gamestream PUBLIC ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${AVAHI_LIBRARIES})
|
||||
|
||||
target_link_libraries (gamestream PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})
|
||||
|
110
libgamestream/sps.c
Normal file
110
libgamestream/sps.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
*
|
||||
* 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 "sps.h"
|
||||
|
||||
#include "h264_stream.h"
|
||||
|
||||
static h264_stream_t* h264_stream;
|
||||
static int initial_width, initial_height;
|
||||
|
||||
static int replay_sps;
|
||||
|
||||
void gs_sps_init(int width, int height) {
|
||||
h264_stream = h264_new();
|
||||
initial_width = width;
|
||||
initial_height = height;
|
||||
}
|
||||
|
||||
PLENTRY gs_sps_fix(PLENTRY entry, int flags) {
|
||||
if (replay_sps == 1) {
|
||||
PLENTRY replay_entry = malloc(sizeof(LENTRY));
|
||||
char *buffer = malloc(128);
|
||||
if (replay_entry == NULL || buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
char spsData[] = {0x00, 0x00, 0x00, 0x01, 0x67};
|
||||
memcpy(buffer, spsData, sizeof(spsData));
|
||||
h264_stream->sps->profile_idc = H264_PROFILE_HIGH;
|
||||
replay_entry->length = write_nal_unit(h264_stream, buffer+4, 124) + 4;
|
||||
|
||||
replay_entry->data = buffer;
|
||||
replay_entry->next = entry;
|
||||
entry = replay_entry;
|
||||
replay_sps = 2;
|
||||
return replay_entry;
|
||||
} else if ((entry->data[4] & 0x1F) == NAL_UNIT_TYPE_SPS) {
|
||||
read_nal_unit(h264_stream, entry->data+4, entry->length-4);
|
||||
free(entry->data);
|
||||
|
||||
// Some decoders rely on H264 level to decide how many buffers are needed
|
||||
// Since we only need one frame buffered, we'll set level as low as we can
|
||||
// for known resolution combinations. Otherwise leave the profile alone (currently 5.0)
|
||||
if (initial_width == 1280 && initial_height == 720)
|
||||
h264_stream->sps->level_idc = 32; // Max 5 buffered frames at 1280x720x60
|
||||
else if (initial_width = 1920 && initial_height == 1080)
|
||||
h264_stream->sps->level_idc = 42; // Max 4 buffered frames at 1920x1080x60
|
||||
|
||||
// Some decoders requires a reference frame count of 1 to decode successfully.
|
||||
h264_stream->sps->num_ref_frames = 1;
|
||||
|
||||
// GFE 2.5.11 changed the SPS to add additional extensions
|
||||
// Some devices don't like these so we remove them here.
|
||||
h264_stream->sps->vui.video_signal_type_present_flag = 0;
|
||||
h264_stream->sps->vui.chroma_loc_info_present_flag = 0;
|
||||
|
||||
if ((flags & GS_SPS_BITSTREAM_FIXUP) == GS_SPS_BITSTREAM_FIXUP) {
|
||||
// The SPS that comes in the current H264 bytestream doesn't set the bitstream_restriction_flag
|
||||
// or the max_dec_frame_buffering which increases decoding latency on some devices
|
||||
// log2_max_mv_length_horizontal and log2_max_mv_length_vertical are set to more
|
||||
// conservite values by GFE 25.11. We'll let those values stand.
|
||||
if (!h264_stream->sps->vui.bitstream_restriction_flag) {
|
||||
h264_stream->sps->vui.bitstream_restriction_flag = 1;
|
||||
h264_stream->sps->vui.motion_vectors_over_pic_boundaries_flag = 1;
|
||||
h264_stream->sps->vui.max_bits_per_mb_denom = 1;
|
||||
h264_stream->sps->vui.log2_max_mv_length_horizontal = 16;
|
||||
h264_stream->sps->vui.log2_max_mv_length_vertical = 16;
|
||||
h264_stream->sps->vui.num_reorder_frames = 0;
|
||||
}
|
||||
|
||||
// Some devices throw errors if max_dec_frame_buffering < num_ref_frames
|
||||
h264_stream->sps->vui.max_dec_frame_buffering = 1;
|
||||
|
||||
// These values are the default for the fields, but they are more aggressive
|
||||
// than what GFE sends in 2.5.11, but it doesn't seem to cause picture problems.
|
||||
h264_stream->sps->vui.max_bytes_per_pic_denom = 2;
|
||||
h264_stream->sps->vui.max_bits_per_mb_denom = 1;
|
||||
} else // Devices that didn't/couldn't get bitstream restrictions before GFE 2.5.11 will continue to not receive them now
|
||||
h264_stream->sps->vui.bitstream_restriction_flag = 0;
|
||||
|
||||
if ((flags & GS_SPS_BASELINE_HACK) == GS_SPS_BASELINE_HACK && !replay_sps)
|
||||
h264_stream->sps->profile_idc = H264_PROFILE_BASELINE;
|
||||
|
||||
entry->data = malloc(128);
|
||||
if (entry->data == NULL)
|
||||
return NULL;
|
||||
|
||||
entry->length = write_nal_unit(h264_stream, entry->data+4, 124) + 4;
|
||||
} else if ((entry->data[4] & 0x1F) == NAL_UNIT_TYPE_PPS) {
|
||||
if ((flags & GS_SPS_BASELINE_HACK) == GS_SPS_BASELINE_HACK && !replay_sps)
|
||||
replay_sps = 1;
|
||||
|
||||
}
|
||||
return entry;
|
||||
}
|
26
libgamestream/sps.h
Normal file
26
libgamestream/sps.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of Moonlight Embedded.
|
||||
*
|
||||
* Copyright (C) 2015 Iwan Timmer
|
||||
*
|
||||
* 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"
|
||||
|
||||
#define GS_SPS_BITSTREAM_FIXUP 0x01
|
||||
#define GS_SPS_BASELINE_HACK 0x02
|
||||
|
||||
void gs_sps_init();
|
||||
PLENTRY gs_sps_fix(PLENTRY entry, int flags);
|
@ -28,10 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
// Video decode on Raspberry Pi using OpenMAX IL though the ilcient helper library
|
||||
// Based upon video decode example from the Raspberry Pi firmware
|
||||
|
||||
#include "sps.h"
|
||||
#include "../video.h"
|
||||
|
||||
#include "h264_stream.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -51,16 +50,9 @@ static unsigned char *dest;
|
||||
static int port_settings_changed;
|
||||
static int first_packet;
|
||||
|
||||
static h264_stream_t* stream;
|
||||
|
||||
static void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) {
|
||||
stream = h264_new();
|
||||
if (stream == NULL) {
|
||||
fprintf(stderr, "Not enough memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bcm_host_init();
|
||||
gs_sps_init(width, height);
|
||||
|
||||
OMX_VIDEO_PARAM_PORTFORMATTYPE format;
|
||||
OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
|
||||
@ -179,22 +171,7 @@ static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
|
||||
first_packet = 0;
|
||||
}
|
||||
|
||||
PLENTRY entry = decodeUnit->bufferList;
|
||||
if (entry != NULL && entry->data[4] == 0x67) {
|
||||
read_nal_unit(stream, entry->data+4, entry->length-4);
|
||||
stream->sps->num_ref_frames = 1;
|
||||
stream->sps->vui.bitstream_restriction_flag = 1;
|
||||
stream->sps->vui.motion_vectors_over_pic_boundaries_flag = 1;
|
||||
stream->sps->vui.max_bytes_per_pic_denom = 2;
|
||||
stream->sps->vui.max_bits_per_mb_denom = 1;
|
||||
stream->sps->vui.log2_max_mv_length_horizontal = 16;
|
||||
stream->sps->vui.log2_max_mv_length_vertical = 16;
|
||||
stream->sps->vui.num_reorder_frames = 0;
|
||||
stream->sps->vui.max_dec_frame_buffering = 1;
|
||||
|
||||
entry->length = write_nal_unit(stream, entry->data+4, entry->length*2) + 4;
|
||||
}
|
||||
|
||||
PLENTRY entry = gs_sps_fix(decodeUnit->bufferList, GS_SPS_BITSTREAM_FIXUP);
|
||||
while (entry != NULL) {
|
||||
memcpy(dest, entry->data, entry->length);
|
||||
buf->nFilledLen += entry->length;
|
||||
@ -228,4 +205,5 @@ DECODER_RENDERER_CALLBACKS decoder_callbacks_omx = {
|
||||
.setup = decoder_renderer_setup,
|
||||
.cleanup = decoder_renderer_cleanup,
|
||||
.submitDecodeUnit = decoder_renderer_submit_decode_unit,
|
||||
.capabilities = CAPABILITY_NEEDS_SPS_CLEANUP | CAPABILITY_NEEDS_SPS_BITSTREAM_FIXUP,
|
||||
};
|
||||
|
2
third_party/moonlight-common-c
vendored
2
third_party/moonlight-common-c
vendored
@ -1 +1 @@
|
||||
Subproject commit 109e3ca537e6640e9bfb6f1a234c4c961ead10fe
|
||||
Subproject commit d67071cf0e53e0c6d6429d742ff5213da3dbba5e
|
Loading…
x
Reference in New Issue
Block a user