Petri Hintukainen pushed to branch master at VideoLAN / libbluray
Commits:
4c785b60 by Masstock at 2026-01-18T23:42:43+01:00
Enforce UO restriction level
- - - - -
3 changed files:
- src/libbluray/bdnav/uo_mask_table.h
- src/libbluray/bluray.c
- src/libbluray/bluray.h
Changes:
=====================================
src/libbluray/bdnav/uo_mask_table.h
=====================================
@@ -20,10 +20,38 @@
#if !defined(_BD_UO_MASK_TABLE_H_)
#define _BD_UO_MASK_TABLE_H_
-enum {
- UO_MASK_MENU_CALL_INDEX = 0,
- UO_MASK_TITLE_SEARCH_INDEX = 1,
-};
+typedef enum {
+ UO_MASK_MENU_CALL_INDEX = 0,
+ UO_MASK_TITLE_SEARCH_INDEX = 1,
+ UO_MASK_CHAPTER_SEARCH_INDEX = 2,
+ UO_MASK_TIME_SEARCH_MASK_INDEX = 3,
+ UO_MASK_SKIP_TO_NEXT_POINT_MASK_INDEX = 4,
+ UO_MASK_SKIP_BACK_TO_PREVIOUS_POINT_MASK_INDEX = 5,
+ UO_MASK_STOP_MASK_INDEX = 7,
+ UO_MASK_PAUSE_ON_MASK_INDEX = 8,
+ UO_MASK_STILL_OFF_MASK_INDEX = 10,
+ UO_MASK_FORWARD_PLAY_MASK_INDEX = 11,
+ UO_MASK_BACKWARD_PLAY_MASK_INDEX = 12,
+ UO_MASK_RESUME_MASK_INDEX = 13,
+ UO_MASK_MOVE_UP_SELECTED_BUTTON_MASK_INDEX = 14,
+ UO_MASK_MOVE_DOWN_SELECTED_BUTTON_MASK_INDEX = 15,
+ UO_MASK_MOVE_LEFT_SELECTED_BUTTON_MASK_INDEX = 16,
+ UO_MASK_MOVE_RIGHT_SELECTED_BUTTON_MASK_INDEX = 17,
+ UO_MASK_SELECT_BUTTON_MASK_INDEX = 18,
+ UO_MASK_ACTIVATE_BUTTON_MASK_INDEX = 19,
+ UO_MASK_SELECT_AND_ACTIVATE_MASK_INDEX = 20,
+ UO_MASK_PRIMARY_AUDIO_CHANGE_MASK_INDEX = 21,
+ UO_MASK_ANGLE_CHANGE_MASK_INDEX = 23,
+ UO_MASK_POPUP_ON_MASK_INDEX = 24,
+ UO_MASK_POPUP_OFF_MASK_INDEX = 25,
+ UO_MASK_PG_TEXTST_ENABLE_DISABLE_MASK_INDEX = 26,
+ UO_MASK_PG_TEXTST_CHANGE_MASK_INDEX = 27,
+ UO_MASK_SECONDARY_VIDEO_ENABLE_DISABLE_MASK_INDEX = 28,
+ UO_MASK_SECONDARY_VIDEO_CHANGE_MASK_INDEX = 29,
+ UO_MASK_SECONDARY_AUDIO_ENABLE_DISABLE_MASK_INDEX = 30,
+ UO_MASK_SECONDARY_AUDIO_CHANGE_MASK_INDEX = 31,
+ UO_MASK_PIP_PG_TEXTST_CHANGE_MASK_INDEX = 33,
+} bd_uo_mask_index_e;
typedef struct bd_uo_mask_table
{
=====================================
src/libbluray/bluray.c
=====================================
@@ -1227,7 +1227,7 @@ void bd_set_bdj_uo_mask(BLURAY *bd, unsigned mask)
uint64_t bd_get_uo_mask(BLURAY *bd)
{
- /* internal function. Used by BD-J. */
+ /* internal function. Used by BD-J (and UO masking checks). */
union {
uint64_t u64;
BD_UO_MASK mask;
@@ -1240,6 +1240,11 @@ uint64_t bd_get_uo_mask(BLURAY *bd)
return mask.u64;
}
+static int _is_uo_masked(BLURAY *bd, bd_uo_mask_index_e mask_index)
+{
+ return (bd->title_type != title_undef) && !!(bd_get_uo_mask(bd) & (1ull <<
mask_index));
+}
+
void bd_set_bdj_kit(BLURAY *bd, int mask)
{
_queue_event(bd, BD_EVENT_KEY_INTEREST_TABLE, mask);
@@ -1277,6 +1282,8 @@ void bd_select_rate(BLURAY *bd, float rate, int reason)
}
}
+static int64_t _seek_time(BLURAY *bd, uint64_t tick, uint8_t
is_uo_mask_checked);
+
int bd_bdj_seek(BLURAY *bd, int playitem, int playmark, int64_t time)
{
bd_mutex_lock(&bd->mutex);
@@ -1288,7 +1295,7 @@ int bd_bdj_seek(BLURAY *bd, int playitem, int playmark,
int64_t time)
bd_seek_mark(bd, playmark);
}
if (time >= 0) {
- bd_seek_time(bd, time);
+ _seek_time(bd, time, 0);
}
bd_mutex_unlock(&bd->mutex);
@@ -1750,7 +1757,7 @@ static void _change_angle(BLURAY *bd)
}
}
-int64_t bd_seek_time(BLURAY *bd, uint64_t tick)
+static int64_t _seek_time(BLURAY *bd, uint64_t tick, uint8_t
is_uo_mask_checked)
{
uint32_t clip_pkt, out_pkt;
const NAV_CLIP *clip;
@@ -1760,9 +1767,18 @@ int64_t bd_seek_time(BLURAY *bd, uint64_t tick)
return bd->s_pos;
}
- tick /= 2;
+ tick /= 2; // Convert to 45kHz clock ticks
- bd_mutex_lock(&bd->mutex);
+ /* Check UO mask */
+ if (is_uo_mask_checked) {
+ const bd_uo_mask_index_e uo_mask_idx = UO_MASK_TIME_SEARCH_MASK_INDEX;
+
+ if (_is_uo_masked(bd, uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_seek_time(%" PRIu64 ") UO %d
restricted\n", tick, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, uo_mask_idx);
+ return -1;
+ }
+ }
if (bd->title &&
tick < bd->title->duration) {
@@ -1775,12 +1791,23 @@ int64_t bd_seek_time(BLURAY *bd, uint64_t tick)
_seek_internal(bd, clip, out_pkt, clip_pkt);
} else {
- BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_seek_time(%u) failed\n", (unsigned
int)tick);
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_seek_time(%" PRIu64 ") failed\n",
tick);
}
+ return bd->s_pos;
+}
+
+int64_t bd_seek_time(BLURAY *bd, uint64_t tick)
+{
+ int64_t ret = 0;
+
+ bd_mutex_lock(&bd->mutex);
+
+ ret = _seek_time(bd, tick, BLURAY_PLAYER_SETTING_UO_RESTRICTION_SAFE <=
bd->uo_restriction_level);
+
bd_mutex_unlock(&bd->mutex);
- return bd->s_pos;
+ return ret;
}
uint64_t bd_tell_time(BLURAY *bd)
@@ -1808,28 +1835,42 @@ uint64_t bd_tell_time(BLURAY *bd)
int64_t bd_seek_chapter(BLURAY *bd, unsigned chapter)
{
+ int is_uo_mask_checked;
uint32_t clip_pkt, out_pkt;
const NAV_CLIP *clip;
+ int64_t ret_pos;
bd_mutex_lock(&bd->mutex);
+ is_uo_mask_checked = (BLURAY_PLAYER_SETTING_UO_RESTRICTION_SAFE <
bd->uo_restriction_level);
- if (bd->title &&
- chapter < bd->title->chap_list.count) {
+ ret_pos = bd->s_pos; // Return current position by default
+ if (bd->title && chapter < bd->title->chap_list.count) {
+ /* Check chapter jump direction for UO restriction */
+ const bd_uo_mask_index_e uo_mask_idx = UO_MASK_CHAPTER_SEARCH_INDEX;
_change_angle(bd);
- // Find the closest access unit to the requested position
- clip = nav_chapter_search(bd->title, chapter, &clip_pkt, &out_pkt);
+ if (is_uo_mask_checked && _is_uo_masked(bd, uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_seek_chapter(%u) UO %d
restricted\n", chapter, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, uo_mask_idx);
+ ret_pos = -1;
+ } else {
+ /* Seek chapter */
+ _change_angle(bd);
- _seek_internal(bd, clip, out_pkt, clip_pkt);
+ // Find the closest access unit to the requested position
+ clip = nav_chapter_search(bd->title, chapter, &clip_pkt, &out_pkt);
+ _seek_internal(bd, clip, out_pkt, clip_pkt);
+ ret_pos = bd->s_pos; // Update
+ }
} else {
BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_seek_chapter(%u) failed\n",
chapter);
}
bd_mutex_unlock(&bd->mutex);
- return bd->s_pos;
+ return ret_pos;
}
int64_t bd_chapter_pos(BLURAY *bd, unsigned chapter)
@@ -2621,7 +2662,7 @@ uint32_t bd_get_current_title(BLURAY *bd)
return bd->title_idx;
}
-static int _bd_select_angle(BLURAY *bd, unsigned angle)
+static int _bd_select_angle(BLURAY *bd, unsigned angle, uint8_t
is_uo_mask_checked)
{
unsigned orig_angle;
@@ -2630,6 +2671,17 @@ static int _bd_select_angle(BLURAY *bd, unsigned angle)
return 0;
}
+ /* Check UO mask */
+ if (is_uo_mask_checked) {
+ const bd_uo_mask_index_e uo_mask_idx = UO_MASK_ANGLE_CHANGE_MASK_INDEX;
+
+ if (_is_uo_masked(bd, uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_select_angle(%u) UO %d
restricted\n", angle, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, uo_mask_idx);
+ return 0;
+ }
+ }
+
orig_angle = bd->title->angle;
nav_set_angle(bd->title, angle);
@@ -2651,9 +2703,11 @@ static int _bd_select_angle(BLURAY *bd, unsigned angle)
int bd_select_angle(BLURAY *bd, unsigned angle)
{
int result;
+
bd_mutex_lock(&bd->mutex);
- result = _bd_select_angle(bd, angle);
+ result = _bd_select_angle(bd, angle,
BLURAY_PLAYER_SETTING_UO_RESTRICTION_COMPLIANT <= bd->uo_restriction_level);
bd_mutex_unlock(&bd->mutex);
+
return result;
}
@@ -3061,18 +3115,85 @@ int bd_set_player_setting_str(BLURAY *bd, uint32_t idx,
const char *s)
}
}
-void bd_select_stream(BLURAY *bd, uint32_t stream_type, uint32_t stream_id,
uint32_t enable_flag)
+static int _select_audio_stream(BLURAY *bd, uint32_t stream_id, int
is_checked_uo_mask)
+{
+ /* Check Primary Audio Stream Number Change UO */
+ if (is_checked_uo_mask) {
+ const bd_uo_mask_index_e uo_mask_idx =
UO_MASK_PRIMARY_AUDIO_CHANGE_MASK_INDEX;
+
+ if (_is_uo_masked(bd, uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "_select_audio_stream(%" PRIu32 ")
UO %d restricted\n",
+ stream_id, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, uo_mask_idx);
+ return 0;
+ }
+ }
+
+ bd_psr_write(bd->regs, PSR_PRIMARY_AUDIO_ID, stream_id & 0xff);
+ return 1;
+}
+
+static int _select_pg_textst_stream(BLURAY *bd, uint32_t stream_id, uint32_t
enable_flag, int is_checked_uo_mask)
{
+ uint32_t psr_initial_value = 0x0;
+ uint32_t psr_update_value = 0x0;
+ uint32_t psr_update_mask = 0x0;
+
+ /* Get initial PSR value to check for changes */
+ psr_initial_value = bd_psr_read(bd->regs, PSR_PG_STREAM);
+
+ /* Check PG textST Enable Disable UO */
+ if (!enable_flag != !(psr_initial_value & 0x80000000)) {
+ const bd_uo_mask_index_e uo_mask_idx =
UO_MASK_PG_TEXTST_ENABLE_DISABLE_MASK_INDEX;
+
+ if (is_checked_uo_mask && _is_uo_masked(bd, uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "_select_pg_textst_stream(%"
PRIu32 ", %" PRIu32 ") UO %d restricted\n",
+ stream_id, enable_flag, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, uo_mask_idx);
+ } else {
+ // Enable/Disable PSR value
+ psr_update_value |= (!!enable_flag) << 31;
+ psr_update_mask |= 0x80000000;
+ }
+ }
+
+ /* Check PG textST Stream Number Change UO */
+ if (stream_id != (psr_initial_value & 0xfff)) {
+ const bd_uo_mask_index_e uo_mask_idx =
UO_MASK_PG_TEXTST_CHANGE_MASK_INDEX;
+
+ if (is_checked_uo_mask && _is_uo_masked(bd, uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "_select_pg_textst_stream(%"
PRIu32 ", %" PRIu32 ") UO %d restricted\n",
+ stream_id, enable_flag, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, uo_mask_idx);
+ } else {
+ psr_update_value |= stream_id & 0xfff;
+ psr_update_mask |= 0xfff;
+ }
+ }
+
+ if (psr_update_mask) {
+ bd_psr_write_bits(bd->regs, PSR_PG_STREAM, psr_update_value,
psr_update_mask);
+ }
+
+ return !!psr_update_mask;
+}
+
+int bd_select_stream(BLURAY *bd, uint32_t stream_type, uint32_t stream_id,
uint32_t enable_flag)
+{
+ int is_checked_uo_mask = 0;
+ int ret = -1;
+
bd_mutex_lock(&bd->mutex);
+ /* Selecting stream should be a safe UO */
+ is_checked_uo_mask = (BLURAY_PLAYER_SETTING_UO_RESTRICTION_COMPLIANT <=
bd->uo_restriction_level);
+
switch (stream_type) {
case BLURAY_AUDIO_STREAM:
- bd_psr_write(bd->regs, PSR_PRIMARY_AUDIO_ID, stream_id & 0xff);
+ ret = _select_audio_stream(bd, stream_id, is_checked_uo_mask);
break;
case BLURAY_PG_TEXTST_STREAM:
- bd_psr_write_bits(bd->regs, PSR_PG_STREAM,
- ((!!enable_flag)<<31) | (stream_id & 0xfff),
- 0x80000fff);
+ ret = _select_pg_textst_stream(bd, stream_id, enable_flag,
is_checked_uo_mask);
break;
/*
case BLURAY_SECONDARY_VIDEO_STREAM:
@@ -3081,6 +3202,8 @@ void bd_select_stream(BLURAY *bd, uint32_t stream_type,
uint32_t stream_id, uint
}
bd_mutex_unlock(&bd->mutex);
+
+ return ret;
}
/*
@@ -3511,12 +3634,16 @@ static int _try_play_title(BLURAY *bd, unsigned title)
return 0;
}
- if (bd->uo_mask.title_search) {
- BD_DEBUG(DBG_BLURAY | DBG_CRIT, "title search masked\n");
+ if (BLURAY_PLAYER_SETTING_UO_RESTRICTION_RELAXED <=
bd->uo_restriction_level && bd->uo_mask.title_search) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_play_title(): UO title search
masked\n");
+ // FIXME: UO_MASK_TITLE_SEARCH_INDEX is not part of BD-J API
UOMaskTableControl
_bdj_event(bd, BDJ_EVENT_UO_MASKED, UO_MASK_TITLE_SEARCH_INDEX);
+
return 0;
}
+ /* TODO: Check if the title can be accessed */
+
return _play_title(bd, title);
}
@@ -3544,9 +3671,11 @@ static int _try_menu_call(BLURAY *bd, int64_t pts)
return 0;
}
- if (bd->uo_mask.menu_call) {
- BD_DEBUG(DBG_BLURAY | DBG_CRIT, "menu call masked\n");
+ if (BLURAY_PLAYER_SETTING_UO_RESTRICTION_RELAXED <=
bd->uo_restriction_level && bd->uo_mask.menu_call) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_menu_call(): UO menu call
masked\n");
+ // FIXME: UO_MASK_MENU_CALL_INDEX is not part of BD-J API
UOMaskTableControl
_bdj_event(bd, BDJ_EVENT_UO_MASKED, UO_MASK_MENU_CALL_INDEX);
+
return 0;
}
@@ -3795,12 +3924,50 @@ void bd_set_scr(BLURAY *bd, int64_t pts)
bd_mutex_unlock(&bd->mutex);
}
+static int _get_rate_uo_index(BLURAY *bd, uint32_t rate, bd_uo_mask_index_e
*uo_index)
+{
+ if (BLURAY_RATE_PAUSED == rate) {
+ /* Pause On should be a safe UO */
+ if (bd->uo_restriction_level <=
BLURAY_PLAYER_SETTING_UO_RESTRICTION_SAFE) {
+ return 0; // ignore UO restriction
+ }
+ *uo_index = UO_MASK_PAUSE_ON_MASK_INDEX;
+ return 1;
+ }
+
+ /* If current clip is freezed, Still Off UO will certainly break playback
*/
+ if (bd->st0.clip->still_mode >= BLURAY_STILL_TIME) {
+ if (bd->uo_restriction_level <=
BLURAY_PLAYER_SETTING_UO_RESTRICTION_SAFE) {
+ return 0; // ignore UO restriction
+ }
+ *uo_index = UO_MASK_STILL_OFF_MASK_INDEX;
+ return 1;
+ }
+
+ /* use Forward Play UO, as libbluray does not consider backward play */
+ if (bd->uo_restriction_level <= BLURAY_PLAYER_SETTING_UO_RESTRICTION_SAFE)
{
+ return 0; // ignore UO restriction
+ }
+
+ *uo_index = UO_MASK_FORWARD_PLAY_MASK_INDEX;
+ return 1;
+}
+
static int _set_rate(BLURAY *bd, uint32_t rate)
{
+ bd_uo_mask_index_e uo_mask_idx = 0;
+
if (!bd->title) {
return -1;
}
+ if (_get_rate_uo_index(bd, rate, &uo_mask_idx) && _is_uo_masked(bd,
uo_mask_idx)) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_set_rate(%" PRIu32 ") UO %d
restricted\n",
+ rate, uo_mask_idx);
+ _bdj_event(bd, BDJ_EVENT_UO_MASKED, (unsigned) uo_mask_idx);
+ return -1;
+ }
+
if (bd->title_type == title_bdj) {
return _bdj_event(bd, BDJ_EVENT_RATE, rate);
}
@@ -3839,6 +4006,47 @@ int bd_mouse_select(BLURAY *bd, int64_t pts, uint16_t x,
uint16_t y)
return result;
}
+static int _get_key_uo_index(BLURAY *bd, uint32_t key_id, bd_uo_mask_index_e
*uo_index)
+{
+ unsigned i;
+
+ static const struct {
+ bd_vk_key_e key;
+ bd_uo_mask_index_e uo_index;
+ bd_player_setting_uo_restriction_level uo_min_level;
+ } key_uo_map[] = {
+#define D(k, i, l) { k, UO_MASK_ ## i, BLURAY_PLAYER_SETTING_UO_RESTRICTION_
## l }
+ D(BD_VK_ROOT_MENU, MENU_CALL_INDEX, SAFE),
+ /* BD_VK_POPUP handled specifically */
+ D(BD_VK_UP, MOVE_UP_SELECTED_BUTTON_MASK_INDEX, COMPLIANT),
+ D(BD_VK_DOWN, MOVE_DOWN_SELECTED_BUTTON_MASK_INDEX, COMPLIANT),
+ D(BD_VK_LEFT, MOVE_LEFT_SELECTED_BUTTON_MASK_INDEX, COMPLIANT),
+ D(BD_VK_RIGHT, MOVE_RIGHT_SELECTED_BUTTON_MASK_INDEX, COMPLIANT),
+ D(BD_VK_ENTER, ACTIVATE_BUTTON_MASK_INDEX, COMPLIANT),
+#undef D
+ };
+
+ if (BD_VK_POPUP == key_id) {
+ /* check if pop-up menu is on, if so key is treated as Pop-up Off UO */
+ if (bd->uo_restriction_level <=
BLURAY_PLAYER_SETTING_UO_RESTRICTION_SAFE) {
+ return 0; // Not enforced
+ }
+ return (bd->gc_status & GC_STATUS_POPUP) ?
UO_MASK_POPUP_OFF_MASK_INDEX : UO_MASK_POPUP_ON_MASK_INDEX;
+ }
+
+ for (i = 0; i < sizeof(key_uo_map) / sizeof(key_uo_map[0]); i++) {
+ if (key_uo_map[i].key == key_id) {
+ if (bd->uo_restriction_level < key_uo_map[i].uo_min_level) {
+ return 0; // Not enforced
+ }
+ *uo_index = key_uo_map[i].uo_index;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
#define BD_VK_FLAGS_MASK (BD_VK_KEY_PRESSED | BD_VK_KEY_TYPED |
BD_VK_KEY_RELEASED)
#define BD_VK_KEY(k) ((k) & ~(BD_VK_FLAGS_MASK))
#define BD_VK_FLAGS(k) ((k) & BD_VK_FLAGS_MASK)
@@ -3847,6 +4055,8 @@ int bd_mouse_select(BLURAY *bd, int64_t pts, uint16_t x,
uint16_t y)
int bd_user_input(BLURAY *bd, int64_t pts, uint32_t key)
{
+ bd_uo_mask_index_e uo_mask_idx = 0;
+ int uo_is_masked = 0;
int result = -1;
if (BD_VK_KEY(key) == BD_VK_ROOT_MENU) {
@@ -3859,10 +4069,18 @@ int bd_user_input(BLURAY *bd, int64_t pts, uint32_t key)
bd_mutex_lock(&bd->mutex);
_set_scr(bd, pts);
+ if (_get_key_uo_index(bd, BD_VK_KEY(key), &uo_mask_idx)) {
+ uo_is_masked = _is_uo_masked(bd, uo_mask_idx);
+ }
if (bd->title_type == title_hdmv) {
if (BD_KEY_TYPED(key)) {
- result = _run_gc(bd, GC_CTRL_VK_KEY, BD_VK_KEY(key));
+ if (uo_is_masked) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_user_input(%" PRIu32 ") UO
%d restricted\n", key, uo_mask_idx);
+ result = 0;
+ } else {
+ result = _run_gc(bd, GC_CTRL_VK_KEY, BD_VK_KEY(key));
+ }
} else {
result = 0;
}
=====================================
src/libbluray/bluray.h
=====================================
@@ -535,7 +535,8 @@ BD_PUBLIC int bd_read(BLURAY *bd, unsigned char *buf, int
len);
*/
/**
- * Seek to pos in currently selected title
+ *
+ * Seek to pos in currently selected title.
*
* @param bd BLURAY object
* @param pos position to seek to
@@ -545,21 +546,26 @@ BD_PUBLIC int64_t bd_seek(BLURAY *bd, uint64_t pos);
/**
*
- * Seek to specific time in 90Khz ticks
+ * Seek to specific time in 90Khz ticks.
*
- * @param bd BLURAY ojbect
- * @param tick tick count
- * @return current seek position
+ * May fail if UO mask bit BLURAY_UO_TIME_SEARCH_MASK is set.
+ *
+ * @param bd BLURAY object
+ * @param tick tick count
+ * @return <0 on UO mask restriction, current seek position otherwise
*/
BD_PUBLIC int64_t bd_seek_time(BLURAY *bd, uint64_t tick);
/**
*
- * Seek to a chapter. First chapter is 0
+ * Seek to a chapter.
+ *
+ * First chapter is 0.
+ * May fail if UO mask bit BLURAY_UO_CHAPTER_SEARCH is set.
*
* @param bd BLURAY object
* @param chapter chapter to seek to
- * @return current seek position
+ * @return <0 on UO mask restriction, current seek position otherwise
*/
BD_PUBLIC int64_t bd_seek_chapter(BLURAY *bd, unsigned chapter);
@@ -585,7 +591,9 @@ BD_PUBLIC int64_t bd_seek_playitem(BLURAY *bd, unsigned
clip_ref);
/**
*
- * Set the angle to play
+ * Set the angle to play.
+ *
+ * May fail if UO mask bit UO_MASK_ANGLE_CHANGE_MASK_INDEX is set.
*
* @param bd BLURAY object
* @param angle angle to play
@@ -619,12 +627,22 @@ BD_PUBLIC void bd_seamless_angle_change(BLURAY *bd,
unsigned angle);
* Without on-disc menus selecting the stream is useful only when using
* libbluray internal decoders or the stream is stored in a sub-path.
*
+ * Depending on stream type, may fail if one of the following UO mask bit is
set:
+ * - UO_MASK_PRIMARY_AUDIO_CHANGE_MASK_INDEX (BLURAY_AUDIO_STREAM);
+ * - UO_MASK_PG_TEXTST_ENABLE_DISABLE_MASK_INDEX (BLURAY_PG_TEXTST_STREAM);
+ * - UO_MASK_PG_TEXTST_CHANGE_MASK_INDEX (BLURAY_PG_TEXTST_STREAM);
+ * or if the requested stream number is out of range. If multiple changes are
+ * made (e.g. enable and change PG/TextST track), the non-masked UOs are
+ * applied (but this function might still return 0 if at least one change was
+ * prohibited).
+ *
* @param bd BLURAY object
* @param stream_type BLURAY_AUDIO_STREAM or BLURAY_PG_TEXTST_STREAM
* @param stream_id stream number (1..N)
* @param enable_flag set to 0 to disable streams of this type
+ * @return <0 on error, 1 if the stream was selected, 0 if no change was made,
or was prevented by the UO mask
*/
-BD_PUBLIC void bd_select_stream(BLURAY *bd, uint32_t stream_type, uint32_t
stream_id, uint32_t enable_flag);
+BD_PUBLIC int bd_select_stream(BLURAY *bd, uint32_t stream_type, uint32_t
stream_id, uint32_t enable_flag);
#define BLURAY_AUDIO_STREAM 0 /**< Select audio stream */
#define BLURAY_PG_TEXTST_STREAM 1 /**< Select subtitle stream */
@@ -720,9 +738,9 @@ typedef enum {
BLURAY_PLAYER_SETTING_PERSISTENT_STORAGE = 0x101, /**< Enable/disable
BD-J persistent storage. Integer. Default: enabled. */
BLURAY_PLAYER_SETTING_UO_RESTRICTION_LEVEL = 0x102, /**< Set User
Operations (UO) restriction mask enforcement level.
bd_player_setting_uo_restriction_level value. Default:
BLURAY_PLAYER_SETTING_UO_RESTRICTION_RELAXED. */
- BLURAY_PLAYER_PERSISTENT_ROOT = 0x200, /**< Root path to the
BD_J persistent storage location. String. */
- BLURAY_PLAYER_CACHE_ROOT = 0x201, /**< Root path to the
BD_J cache storage location. String. */
- BLURAY_PLAYER_JAVA_HOME = 0x202, /**< Location of JRE.
String. Default: NULL (autodetect). */
+ BLURAY_PLAYER_PERSISTENT_ROOT = 0x200, /**< Root path to the
BD_J persistent storage location. String. */
+ BLURAY_PLAYER_CACHE_ROOT = 0x201, /**< Root path to the
BD_J cache storage location. String. */
+ BLURAY_PLAYER_JAVA_HOME = 0x202, /**< Location of JRE.
String. Default: NULL (autodetect). */
} bd_player_setting;
/** Player User Operation (UO) restriction mask enforcement level. */
@@ -1034,6 +1052,7 @@ BD_PUBLIC int bd_play_title(BLURAY *bd, unsigned title);
* Open BluRay disc Top Menu.
*
* Current pts is needed for resuming playback when menu is closed.
+ * May fail if UO mask bit BLURAY_UO_MENU_CALL is set.
*
* @param bd BLURAY object
* @param pts current playback position (1/90000s) or -1
@@ -1128,6 +1147,16 @@ BD_PUBLIC int bd_set_rate(BLURAY *bd, uint32_t rate);
* - Separate events when key is pressed and released.
* VD_VK_KEY_PRESSED, BD_VK_TYPED and BD_VK_KEY_RELEASED are or'd with
the key.
*
+ * Depending on the action, may fail if one of the following UO mask bit is
set:
+ * - UO_MASK_MENU_CALL_INDEX (BD_VK_ROOT_MENU);
+ * - UO_MASK_MOVE_UP_SELECTED_BUTTON_MASK_INDEX (BD_VK_UP);
+ * - UO_MASK_MOVE_DOWN_SELECTED_BUTTON_MASK_INDEX (BD_VK_DOWN);
+ * - UO_MASK_MOVE_LEFT_SELECTED_BUTTON_MASK_INDEX (BD_VK_LEFT);
+ * - UO_MASK_MOVE_RIGHT_SELECTED_BUTTON_MASK_INDEX (BD_VK_RIGHT);
+ * - UO_MASK_ACTIVATE_BUTTON_MASK_INDEX (BD_VK_ENTER);
+ * - UO_MASK_POPUP_ON_MASK_INDEX (BD_VK_POPUP);
+ * - UO_MASK_POPUP_OFF_MASK_INDEX (BD_VK_POPUP);
+ *
* @param bd BLURAY object
* @param pts current playback position (1/90000s) or -1
* @param key input key (@see keys.h)
View it on GitLab:
https://code.videolan.org/videolan/libbluray/-/commit/4c785b60d70492ef7b682cbc6f8d11ed62233b8e
--
View it on GitLab:
https://code.videolan.org/videolan/libbluray/-/commit/4c785b60d70492ef7b682cbc6f8d11ed62233b8e
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance_______________________________________________
libbluray-devel mailing list
[email protected]
https://mailman.videolan.org/listinfo/libbluray-devel