Merge pull request #6887 from jpark37/priority-parse
libobs: obs-ffmpeg: Update codec priority handling
This commit is contained in:
commit
842c04ecee
@ -51,19 +51,11 @@ const uint8_t *obs_avc_find_startcode(const uint8_t *p, const uint8_t *end)
|
||||
return obs_nal_find_startcode(p, end);
|
||||
}
|
||||
|
||||
static inline int get_drop_priority(int priority)
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
|
||||
static void serialize_avc_data(struct serializer *s, const uint8_t *data,
|
||||
size_t size, bool *is_keyframe, int *priority)
|
||||
{
|
||||
const uint8_t *nal_start, *nal_end;
|
||||
const uint8_t *end = data + size;
|
||||
int type;
|
||||
|
||||
nal_start = obs_avc_find_startcode(data, end);
|
||||
const uint8_t *const end = data + size;
|
||||
const uint8_t *nal_start = obs_nal_find_startcode(data, end);
|
||||
while (true) {
|
||||
while (nal_start < end && !*(nal_start++))
|
||||
;
|
||||
@ -71,18 +63,23 @@ static void serialize_avc_data(struct serializer *s, const uint8_t *data,
|
||||
if (nal_start == end)
|
||||
break;
|
||||
|
||||
type = nal_start[0] & 0x1F;
|
||||
const int type = nal_start[0] & 0x1F;
|
||||
|
||||
if (type == OBS_NAL_SLICE_IDR || type == OBS_NAL_SLICE) {
|
||||
if (is_keyframe)
|
||||
*is_keyframe = (type == OBS_NAL_SLICE_IDR);
|
||||
if (priority)
|
||||
*priority = nal_start[0] >> 5;
|
||||
switch (type) {
|
||||
case OBS_NAL_SLICE:
|
||||
if (*priority < OBS_NAL_PRIORITY_HIGH)
|
||||
*priority = OBS_NAL_PRIORITY_HIGH;
|
||||
break;
|
||||
case OBS_NAL_SLICE_IDR:
|
||||
*is_keyframe = true;
|
||||
*priority = OBS_NAL_PRIORITY_HIGHEST;
|
||||
}
|
||||
|
||||
nal_end = obs_avc_find_startcode(nal_start, end);
|
||||
s_wb32(s, (uint32_t)(nal_end - nal_start));
|
||||
s_write(s, nal_start, nal_end - nal_start);
|
||||
const uint8_t *const nal_end =
|
||||
obs_nal_find_startcode(nal_start, end);
|
||||
const size_t size = nal_end - nal_start;
|
||||
s_wb32(s, (uint32_t)size);
|
||||
s_write(s, nal_start, size);
|
||||
nal_start = nal_end;
|
||||
}
|
||||
}
|
||||
@ -103,7 +100,7 @@ void obs_parse_avc_packet(struct encoder_packet *avc_packet,
|
||||
|
||||
avc_packet->data = output.bytes.array + sizeof(ref);
|
||||
avc_packet->size = output.bytes.num - sizeof(ref);
|
||||
avc_packet->drop_priority = get_drop_priority(avc_packet->priority);
|
||||
avc_packet->drop_priority = avc_packet->priority;
|
||||
}
|
||||
|
||||
static inline bool has_start_code(const uint8_t *data)
|
||||
@ -121,7 +118,7 @@ static void get_sps_pps(const uint8_t *data, size_t size, const uint8_t **sps,
|
||||
const uint8_t *end = data + size;
|
||||
int type;
|
||||
|
||||
nal_start = obs_avc_find_startcode(data, end);
|
||||
nal_start = obs_nal_find_startcode(data, end);
|
||||
while (true) {
|
||||
while (nal_start < end && !*(nal_start++))
|
||||
;
|
||||
@ -129,7 +126,7 @@ static void get_sps_pps(const uint8_t *data, size_t size, const uint8_t **sps,
|
||||
if (nal_start == end)
|
||||
break;
|
||||
|
||||
nal_end = obs_avc_find_startcode(nal_start, end);
|
||||
nal_end = obs_nal_find_startcode(nal_start, end);
|
||||
|
||||
type = nal_start[0] & 0x1F;
|
||||
if (type == OBS_NAL_SPS) {
|
||||
@ -195,7 +192,7 @@ void obs_extract_avc_headers(const uint8_t *packet, size_t size,
|
||||
da_init(header);
|
||||
da_init(sei);
|
||||
|
||||
nal_start = obs_avc_find_startcode(packet, end);
|
||||
nal_start = obs_nal_find_startcode(packet, end);
|
||||
nal_end = NULL;
|
||||
while (nal_end != end) {
|
||||
nal_codestart = nal_start;
|
||||
@ -208,7 +205,7 @@ void obs_extract_avc_headers(const uint8_t *packet, size_t size,
|
||||
|
||||
const uint8_t type = nal_start[0] & 0x1F;
|
||||
|
||||
nal_end = obs_avc_find_startcode(nal_start, end);
|
||||
nal_end = obs_nal_find_startcode(nal_start, end);
|
||||
if (!nal_end)
|
||||
nal_end = end;
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/c99defs.h"
|
||||
#include "obs-nal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -39,13 +39,6 @@ enum {
|
||||
OBS_NAL_FILLER = 12,
|
||||
};
|
||||
|
||||
enum {
|
||||
OBS_NAL_PRIORITY_DISPOSABLE = 0,
|
||||
OBS_NAL_PRIORITY_LOW = 1,
|
||||
OBS_NAL_PRIORITY_HIGH = 2,
|
||||
OBS_NAL_PRIORITY_HIGHEST = 3,
|
||||
};
|
||||
|
||||
/* Helpers for parsing AVC NAL units. */
|
||||
|
||||
EXPORT bool obs_avc_keyframe(const uint8_t *data, size_t size);
|
||||
|
@ -17,8 +17,9 @@
|
||||
|
||||
#include "obs-hevc.h"
|
||||
|
||||
#include "obs.h"
|
||||
#include "obs-nal.h"
|
||||
#include "util/darray.h"
|
||||
#include "util/array-serializer.h"
|
||||
|
||||
enum {
|
||||
OBS_HEVC_NAL_TRAIL_N = 0,
|
||||
@ -89,6 +90,63 @@ bool obs_hevc_keyframe(const uint8_t *data, size_t size)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void serialize_hevc_data(struct serializer *s, const uint8_t *data,
|
||||
size_t size, bool *is_keyframe, int *priority)
|
||||
{
|
||||
const uint8_t *const end = data + size;
|
||||
const uint8_t *nal_start = obs_nal_find_startcode(data, end);
|
||||
while (true) {
|
||||
while (nal_start < end && !*(nal_start++))
|
||||
;
|
||||
|
||||
if (nal_start == end)
|
||||
break;
|
||||
|
||||
// HEVC contains NAL unit specifier at [6..1] bits of
|
||||
// the byte next to the startcode 0x000001
|
||||
const int type = (nal_start[0] & 0x7F) >> 1;
|
||||
|
||||
// Mark IDR slices as key-frames and set them to highest
|
||||
// priority if needed. Assume other slices are non-key
|
||||
// frames and set their priority as high
|
||||
if (type >= OBS_HEVC_NAL_BLA_W_LP &&
|
||||
type <= OBS_HEVC_NAL_RSV_IRAP_VCL23) {
|
||||
*is_keyframe = 1;
|
||||
*priority = OBS_NAL_PRIORITY_HIGHEST;
|
||||
} else if (type >= OBS_HEVC_NAL_TRAIL_N &&
|
||||
type <= OBS_HEVC_NAL_RASL_R) {
|
||||
if (*priority < OBS_NAL_PRIORITY_HIGH)
|
||||
*priority = OBS_NAL_PRIORITY_HIGH;
|
||||
}
|
||||
|
||||
const uint8_t *const nal_end =
|
||||
obs_nal_find_startcode(nal_start, end);
|
||||
const size_t size = nal_end - nal_start;
|
||||
s_wb32(s, (uint32_t)size);
|
||||
s_write(s, nal_start, size);
|
||||
nal_start = nal_end;
|
||||
}
|
||||
}
|
||||
|
||||
void obs_parse_hevc_packet(struct encoder_packet *hevc_packet,
|
||||
const struct encoder_packet *src)
|
||||
{
|
||||
struct array_output_data output;
|
||||
struct serializer s;
|
||||
long ref = 1;
|
||||
|
||||
array_output_serializer_init(&s, &output);
|
||||
*hevc_packet = *src;
|
||||
|
||||
serialize(&s, &ref, sizeof(ref));
|
||||
serialize_hevc_data(&s, src->data, src->size, &hevc_packet->keyframe,
|
||||
&hevc_packet->priority);
|
||||
|
||||
hevc_packet->data = output.bytes.array + sizeof(ref);
|
||||
hevc_packet->size = output.bytes.num - sizeof(ref);
|
||||
hevc_packet->drop_priority = hevc_packet->priority;
|
||||
}
|
||||
|
||||
void obs_extract_hevc_headers(const uint8_t *packet, size_t size,
|
||||
uint8_t **new_packet_data,
|
||||
size_t *new_packet_size, uint8_t **header_data,
|
||||
|
@ -23,7 +23,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct encoder_packet;
|
||||
|
||||
EXPORT bool obs_hevc_keyframe(const uint8_t *data, size_t size);
|
||||
EXPORT void obs_parse_hevc_packet(struct encoder_packet *hevc_packet,
|
||||
const struct encoder_packet *src);
|
||||
EXPORT void obs_extract_hevc_headers(const uint8_t *packet, size_t size,
|
||||
uint8_t **new_packet_data,
|
||||
size_t *new_packet_size,
|
||||
|
@ -23,6 +23,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
OBS_NAL_PRIORITY_DISPOSABLE = 0,
|
||||
OBS_NAL_PRIORITY_LOW = 1,
|
||||
OBS_NAL_PRIORITY_HIGH = 2,
|
||||
OBS_NAL_PRIORITY_HIGHEST = 3,
|
||||
};
|
||||
|
||||
EXPORT const uint8_t *obs_nal_find_startcode(const uint8_t *p,
|
||||
const uint8_t *end);
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
#include "obs-ffmpeg-mux.h"
|
||||
#include <obs-avc.h>
|
||||
#ifdef ENABLE_HEVC
|
||||
#include <obs-hevc.h>
|
||||
#endif
|
||||
|
||||
#define do_log(level, format, ...) \
|
||||
blog(level, "[ffmpeg hls muxer: '%s'] " format, \
|
||||
@ -292,9 +296,20 @@ void ffmpeg_hls_mux_data(void *data, struct encoder_packet *packet)
|
||||
}
|
||||
|
||||
if (packet->type == OBS_ENCODER_VIDEO) {
|
||||
obs_parse_avc_packet(&tmp_packet, packet);
|
||||
packet->drop_priority = tmp_packet.priority;
|
||||
obs_encoder_packet_release(&tmp_packet);
|
||||
const char *const codec =
|
||||
obs_encoder_get_codec(packet->encoder);
|
||||
if (strcmp(codec, "h264") == 0) {
|
||||
obs_parse_avc_packet(&tmp_packet, packet);
|
||||
packet->drop_priority = tmp_packet.priority;
|
||||
obs_encoder_packet_release(&tmp_packet);
|
||||
}
|
||||
#ifdef ENABLE_HEVC
|
||||
else if (strcmp(codec, "hevc") == 0) {
|
||||
obs_parse_hevc_packet(&tmp_packet, packet);
|
||||
packet->drop_priority = tmp_packet.priority;
|
||||
obs_encoder_packet_release(&tmp_packet);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
obs_encoder_packet_ref(&new_packet, packet);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <obs-avc.h>
|
||||
#include <obs-module.h>
|
||||
#include <obs-hotkey.h>
|
||||
#include <util/circlebuf.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user