Skip to content

Commit

Permalink
feat(decode): Port HDR support, update deps to OBS 29.1.x
Browse files Browse the repository at this point in the history
Signed-off-by: Yibai Zhang <xm1994@gmail.com>
  • Loading branch information
summershrimp committed May 17, 2023
1 parent 37d4a27 commit fde0807
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 53 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules")

# Change obs-plugintemplate to your plugin's name in a machine-readable format (e.g.:
# obs-myawesomeplugin) and set
project(obs-ssp VERSION 0.9.5)
project(obs-ssp VERSION 1.0.0)
add_library(${CMAKE_PROJECT_NAME} MODULE)

# Replace `Your Name Here` with the name (yours or your organization's) you want to see as the
Expand Down Expand Up @@ -71,6 +71,7 @@ target_include_directories(
${CMAKE_PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/lib/ssp/include
${CMAKE_SOURCE_DIR}/ssp_connector)

target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE ENABLE_HEVC)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE OBS::libobs FFmpeg::avcodec FFmpeg::avutil mdns)

# --- End of section ---
Expand Down
46 changes: 23 additions & 23 deletions buildspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,47 @@
"hash": "b51773b97b551cb409603146a97b2827d2a66ec3"
},
"prebuilt": {
"version": "2023-01-22",
"version": "2023-05-07",
"baseUrl": "https://github.com/summershrimp/obs-deps/releases/download",
"label": "Pre-built obs-deps",
"hashes": {
"macos-x86_64": "d7597665261c45e81c2780d6127ae6578428b914b4c862deeebda489d2ee20f9",
"macos-arm64": "29cf7574bb9e6d04bc612b5d2a09a3e3c876eab2f1aa0f0c439ec553f6b8f074",
"macos-universal": "9b908297bc9fe3f764a8943d583bd44c589fd9ff38f32f94c5a60fd95710d1f7",
"windows-x64": "8aad11356ef0ea608c07d170bac4dfba1da4ae71e7291a8bcfd22aeb000ed5e6",
"windows-x86": "a53da059f697d07aa01c85263294b2a68bf092e44248a533986cff8909c0752c"
"macos-x86_64": "e6eb65cbf35ab839d029682b199c6ce11a359df18138b1f2ba372db6aabe9e17",
"macos-arm64": "4655c8c21301c185c18ffceceec0541ba6805b96660d575d9e4f3d962a07ccb1",
"macos-universal": "e041f6d4ce0e4632a13ec8d25a35953405d52d9a5b0875c60e130e2f3dc865ba",
"windows-x64": "81e21b6334f001b0489d062beb26fa656a2fea2cdd449e322e2884d042f4756f",
"windows-x86": "b9ff30b1e0c9a00c300b35503f1734bbded4f51dac86521fc876fd14025b6995"
}
},
"qt5": {
"version": "2023-01-22",
"version": "2023-05-07",
"baseUrl": "https://github.com/summershrimp/obs-deps/releases/download",
"label": "Pre-built Qt5",
"hashes": {
"macos-x86_64": "79a0baf7e0ea2ec1ec7000efc5082a095966c8e1a06806884b691b79be1b6949",
"macos-arm64": "23e0cb299b36414447fc903dceb3b893b0b1b1e5dedca3629ca03d50d25aa137",
"macos-universal": "b12ec3d7dffba2d3618e12546a6d9098173c5fb2cf0b50ded7cb936a7175e060",
"windows-x64": "b2077dadf49350968778c41bf6551d61721e1de1192656c32f3d514c1d874cab",
"windows-x86": "b981a9929ba209de82644b6b6e07f6773332ad0b0eb2763dd3a1cec17883a9e0"
"macos-x86_64": "86ff0d3a3ab7057bca7615ee57992d3c79f79a9ff80b27b91566520560a5f3b0",
"macos-arm64": "d39bc94c742b5d63f608319f934f1312f386da9a9b6db76bf10dce06aa3449a7",
"macos-universal": "6e2d0744f78c5ba55ae6b604509ce30f0c6c52357f7357f64fcece5c2744e58f",
"windows-x64": "ecb53abcdb66436cf7953fd41d2619461582c5d874ad744e522e96f06e505987",
"windows-x86": "3f2f7efd3fb5a6d704a88fdbc77a4bcb2495b229a071068be658d7a3971b62bd"
},
"pdb-hashes": {
"windows-x64": "27fba1f4b99f5156be092b6820b3a70f1d82c6842cae24cc1df1fa115cdec1e5",
"windows-x86": "2a48debe9e2d8d8c32772b46cc00fa21e1982772dc7295b52b1b55c2fb0afe1b"
"windows-x64": "1c66a9724e7548b0a0bc6365fe9b3f87924ad76754e4318a53d62513a5809c54",
"windows-x86": "f5803fa086d82bd2b948c9df3b6a9096a185e340117ab65d4b730fa4744740a2"
}
},
"qt6": {
"version": "2023-01-22",
"version": "2023-05-07",
"baseUrl": "https://github.com/summershrimp/obs-deps/releases/download",
"label": "Pre-built Qt6",
"hashes": {
"macos-x86_64": "f9393fda169ab637c7a9525b97ef29b72dd2c05e58d2fff530f02ccde9d31bd3",
"macos-arm64": "bf17060835f8fd654d67acc0a2a0460546d418890b579787c8a930b5f9f9d3c7",
"macos-universal": "3b652267b4d37075f14e60df07965d085d75969b2b74fb4b02610c6f8cf8e4b9",
"windows-x64": "2a1b74abe58c234002cd20879ebcbe792936577e5a3a8b979610c10302685b09",
"windows-x86": "d4a8325f64414c762a75f9cad65d4800f2149c2837b6a1516a3e74ef26fe3560"
"macos-x86_64": "4eb382e0b5ec5cb58e256af7c76610cf6088f52848bda174f50347c5f6d73c41",
"macos-arm64": "672d11d03430c6b3c7e1d4c5b6af33cc48abf8d9337e9eb31499c500fe12d1ec",
"macos-universal": "68b83c10a50dceaba040887e0ebbdb8eb16398035965a6cb0b6dea3785ad6732",
"windows-x64": "5a29da428e4c270a76730152f6d3428719b5ecfc0885907d7377b2436d0356ec",
"windows-x86": "da96c96d9595c5717a2d1e012e194b7dc248d14b3b075deae69ec88f78c63be7"
},
"pdb-hashes": {
"windows-x64": "9e621185ef54042a3b395dd5511bd99a5fc3d22374759910eb290e6f96fccd9a",
"windows-x86": "892bd078ae37ca31852e6232564afe84045811922b6c29dd4aaded0d4397a292"
"windows-x64": "030459201801935b8e9cfa5279b8a2299f4f178f83f2808385d2d2769270ae94",
"windows-x86": "88f6b7d7e6b5eea0d0c1530e6a352464780e411ffbf495c48ffdd1c8bcd2c887"
}
}
},
Expand Down Expand Up @@ -82,5 +82,5 @@
}
},
"name": "obs-ssp",
"version": "0.11.0"
"version": "0.12.0"
}
104 changes: 77 additions & 27 deletions src/ffmpeg-decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include "ffmpeg-decode.h"
#include "obs-ffmpeg-compat.h"
#include <obs-avc.h>
#ifdef ENABLE_HEVC
#include <obs-hevc.h>
#endif

#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 4, 100)
#define USE_NEW_HARDWARE_CODEC_METHOD
Expand Down Expand Up @@ -125,8 +128,10 @@ int ffmpeg_decode_init(struct ffmpeg_decode *decode, enum AVCodecID id,
return ret;
}

#if LIBAVCODEC_VERSION_MAJOR < 60
if (decode->codec->capabilities & CODEC_CAP_TRUNC)
decode->decoder->flags |= CODEC_FLAG_TRUNC;
#endif

return 0;
}
Expand Down Expand Up @@ -162,6 +167,8 @@ static inline enum video_format convert_pixel_format(int f)
return VIDEO_FORMAT_NV12;
case AV_PIX_FMT_YUYV422:
return VIDEO_FORMAT_YUY2;
case AV_PIX_FMT_YVYU422:
return VIDEO_FORMAT_YVYU;
case AV_PIX_FMT_UYVY422:
return VIDEO_FORMAT_UYVY;
case AV_PIX_FMT_YUV422P:
Expand All @@ -171,8 +178,12 @@ static inline enum video_format convert_pixel_format(int f)
return VIDEO_FORMAT_RGBA;
case AV_PIX_FMT_BGRA:
return VIDEO_FORMAT_BGRA;
case AV_PIX_FMT_YUV420P10LE:
return VIDEO_FORMAT_I010;
case AV_PIX_FMT_BGR0:
return VIDEO_FORMAT_BGRX;
case AV_PIX_FMT_P010LE:
return VIDEO_FORMAT_P010;
default:;
}

Expand Down Expand Up @@ -247,26 +258,28 @@ bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,
size_t size, struct obs_source_audio *audio,
bool *got_output)
{
AVPacket packet = {0};
int got_frame = false;
int ret = 0;

*got_output = false;

copy_data(decode, data, size);

av_init_packet(&packet);
packet.data = decode->packet_buffer;
packet.size = (int)size;

if (!decode->frame) {
decode->frame = av_frame_alloc();
if (!decode->frame)
return false;
}

if (data && size)
ret = avcodec_send_packet(decode->decoder, &packet);
if (data && size) {
AVPacket *packet = av_packet_alloc();
packet->data = decode->packet_buffer;
packet->size = (int)size;

ret = avcodec_send_packet(decode->decoder, packet);

av_packet_free(&packet);
}
if (ret == 0)
ret = avcodec_receive_frame(decode->decoder, decode->frame);

Expand Down Expand Up @@ -298,7 +311,8 @@ bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,
}

static enum video_colorspace
convert_color_space(enum AVColorSpace s, enum AVColorTransferCharacteristic trc)
convert_color_space(enum AVColorSpace s, enum AVColorTransferCharacteristic trc,
enum AVColorPrimaries color_primaries)
{
switch (s) {
case AVCOL_SPC_BT709:
Expand All @@ -309,17 +323,23 @@ convert_color_space(enum AVColorSpace s, enum AVColorTransferCharacteristic trc)
case AVCOL_SPC_SMPTE170M:
case AVCOL_SPC_SMPTE240M:
return VIDEO_CS_601;
case AVCOL_SPC_BT2020_NCL:
return (trc == AVCOL_TRC_ARIB_STD_B67) ? VIDEO_CS_2100_HLG
: VIDEO_CS_2100_PQ;
default:
return VIDEO_CS_DEFAULT;
return (color_primaries == AVCOL_PRI_BT2020)
? ((trc == AVCOL_TRC_ARIB_STD_B67)
? VIDEO_CS_2100_HLG
: VIDEO_CS_2100_PQ)
: VIDEO_CS_DEFAULT;
}
}

bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
size_t size, long long *ts,
size_t size, long long *ts, enum video_colorspace cs,
enum video_range_type range,
struct obs_source_frame2 *frame, bool *got_output)
{
AVPacket packet = {0};
int got_frame = false;

AVFrame *avframe = NULL, *sw_frame = NULL;
Expand All @@ -331,15 +351,6 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,

copy_data(decode, data, size);

av_init_packet(&packet);
packet.data = decode->packet_buffer;
packet.size = (int)size;
packet.pts = *ts;

if (decode->codec->id == AV_CODEC_ID_H264 &&
obs_avc_keyframe(data, size))
packet.flags |= AV_PKT_FLAG_KEY;

if (!decode->frame) {
decode->frame = av_frame_alloc();
}
Expand All @@ -356,7 +367,24 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
avframe = decode->hw_frame;
sw_frame = decode->frame;

ret = avcodec_send_packet(decode->decoder, &packet);
AVPacket *packet = av_packet_alloc();
packet->data = decode->packet_buffer;
packet->size = (int)size;
packet->pts = *ts;

switch (decode->codec->id) {
case AV_CODEC_ID_H264:
if (obs_avc_keyframe(data, size))
packet->flags |= AV_PKT_FLAG_KEY;
#ifdef ENABLE_HEVC
break;
case AV_CODEC_ID_HEVC:
if (obs_hevc_keyframe(data, size))
packet->flags |= AV_PKT_FLAG_KEY;
#endif
}

ret = avcodec_send_packet(decode->decoder, packet);
if (ret < 0) {
blog(LOG_INFO, "Error during decoding\n");
return false;
Expand Down Expand Up @@ -397,12 +425,15 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
: VIDEO_RANGE_PARTIAL;
}

const enum video_colorspace cs = convert_color_space(
tmp_frame->colorspace, tmp_frame->color_trc);
if (cs == VIDEO_CS_DEFAULT) {
cs = convert_color_space(decode->frame->colorspace,
decode->frame->color_trc,
decode->frame->color_primaries);
}

const bool success = video_format_get_parameters(
cs, range, frame->color_matrix, frame->color_range_min,
frame->color_range_max);
const bool success = video_format_get_parameters_for_format(
cs, range, frame->format, frame->color_matrix,
frame->color_range_min, frame->color_range_max);
if (!success) {
blog(LOG_ERROR,
"Failed to get video format "
Expand All @@ -419,9 +450,28 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
frame->height = tmp_frame->height;
frame->flip = false;

switch (decode->frame->color_trc) {
case AVCOL_TRC_BT709:
case AVCOL_TRC_GAMMA22:
case AVCOL_TRC_GAMMA28:
case AVCOL_TRC_SMPTE170M:
case AVCOL_TRC_SMPTE240M:
case AVCOL_TRC_IEC61966_2_1:
frame->trc = VIDEO_TRC_SRGB;
break;
case AVCOL_TRC_SMPTE2084:
frame->trc = VIDEO_TRC_PQ;
break;
case AVCOL_TRC_ARIB_STD_B67:
frame->trc = VIDEO_TRC_HLG;
break;
default:
frame->trc = VIDEO_TRC_DEFAULT;
}

if (frame->format == VIDEO_FORMAT_NONE)
return false;

*got_output = true;
return true;
}
}
1 change: 1 addition & 0 deletions src/ffmpeg-decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ extern bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,

extern bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
size_t size, long long *ts,
enum video_colorspace cs,
enum video_range_type range,
struct obs_source_frame2 *frame,
bool *got_output);
Expand Down
5 changes: 3 additions & 2 deletions src/obs-ssp-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ static void ssp_on_video_data(struct imf::SspH264Data *video, ssp_connection *s)
int64_t ts = video->pts;
bool got_output;
bool success = ffmpeg_decode_video(&s->vdecoder, video->data,
video->len, &ts, VIDEO_RANGE_PARTIAL,
&s->frame, &got_output);
video->len, &ts, VIDEO_CS_DEFAULT,
VIDEO_RANGE_PARTIAL, &s->frame,
&got_output);
if (!success) {
ssp_blog(LOG_WARNING, "Error decoding video");
return;
Expand Down

0 comments on commit fde0807

Please sign in to comment.