Port Android SPS fixes to libgamestream

This commit is contained in:
Iwan Timmer 2015-08-05 19:29:13 +02:00
parent 721b7561c7
commit d5cbd7f69e
6 changed files with 144 additions and 30 deletions

View File

@ -41,7 +41,6 @@ endif()
if(BROADCOM_FOUND) if(BROADCOM_FOUND)
aux_source_directory(./third_party/ilclient SRC_LIST) 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 SRC_LIST ./src/video/omx.c)
list(APPEND MOONLIGHT_DEFINITIONS HAVE_OMX) list(APPEND MOONLIGHT_DEFINITIONS HAVE_OMX)
endif() endif()
@ -75,7 +74,7 @@ if (CEC_FOUND)
endif() endif()
if(BROADCOM_FOUND) 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}) target_link_libraries (moonlight PUBLIC ${BROADCOM_LIBRARIES})
list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS}) list(APPEND MOONLIGHT_DEFINITIONS ${BROADCOM_DEFINITIONS})
endif() endif()

View File

@ -6,6 +6,7 @@ find_package(EXPAT REQUIRED)
pkg_check_modules(AVAHI REQUIRED avahi-client) pkg_check_modules(AVAHI REQUIRED avahi-client)
aux_source_directory(./ GAMESTREAM_SRC_LIST) 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 MOONLIGHT_COMMON_SRC_LIST)
aux_source_directory(../third_party/moonlight-common-c/limelight-common/OpenAES 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(gamestream PROPERTIES SOVERSION 0 VERSION ${MOONLIGHT_VERSION})
set_target_properties(moonlight-common 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 ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${EXPAT_LIBRARIES} ${AVAHI_LIBRARIES})
target_link_libraries (gamestream PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) target_link_libraries (gamestream PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS})

110
libgamestream/sps.c Normal file
View 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
View 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);

View File

@ -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 // Video decode on Raspberry Pi using OpenMAX IL though the ilcient helper library
// Based upon video decode example from the Raspberry Pi firmware // Based upon video decode example from the Raspberry Pi firmware
#include "sps.h"
#include "../video.h" #include "../video.h"
#include "h264_stream.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -51,16 +50,9 @@ static unsigned char *dest;
static int port_settings_changed; static int port_settings_changed;
static int first_packet; static int first_packet;
static h264_stream_t* stream;
static void decoder_renderer_setup(int width, int height, int redrawRate, void* context, int drFlags) { 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(); bcm_host_init();
gs_sps_init(width, height);
OMX_VIDEO_PARAM_PORTFORMATTYPE format; OMX_VIDEO_PARAM_PORTFORMATTYPE format;
OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
@ -179,22 +171,7 @@ static int decoder_renderer_submit_decode_unit(PDECODE_UNIT decodeUnit) {
first_packet = 0; first_packet = 0;
} }
PLENTRY entry = decodeUnit->bufferList; PLENTRY entry = gs_sps_fix(decodeUnit->bufferList, GS_SPS_BITSTREAM_FIXUP);
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;
}
while (entry != NULL) { while (entry != NULL) {
memcpy(dest, entry->data, entry->length); memcpy(dest, entry->data, entry->length);
buf->nFilledLen += entry->length; buf->nFilledLen += entry->length;
@ -228,4 +205,5 @@ DECODER_RENDERER_CALLBACKS decoder_callbacks_omx = {
.setup = decoder_renderer_setup, .setup = decoder_renderer_setup,
.cleanup = decoder_renderer_cleanup, .cleanup = decoder_renderer_cleanup,
.submitDecodeUnit = decoder_renderer_submit_decode_unit, .submitDecodeUnit = decoder_renderer_submit_decode_unit,
.capabilities = CAPABILITY_NEEDS_SPS_CLEANUP | CAPABILITY_NEEDS_SPS_BITSTREAM_FIXUP,
}; };

@ -1 +1 @@
Subproject commit 109e3ca537e6640e9bfb6f1a234c4c961ead10fe Subproject commit d67071cf0e53e0c6d6429d742ff5213da3dbba5e