[libbluray-devel] Preload BluRay Text Subtitle streams. Synchronize text subtitle timing with main path.
hpi1
git at videolan.org
Mon Jun 17 22:15:42 CEST 2013
libbluray | branch: master | hpi1 <hpi1 at anonymous.org> | Mon Jun 17 23:13:00 2013 +0300| [d2d3a07e3a075d9e234a14c7b3351f5cda6e5502] | committer: hpi1
Preload BluRay Text Subtitle streams. Synchronize text subtitle timing with main path.
> http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=d2d3a07e3a075d9e234a14c7b3351f5cda6e5502
---
src/libbluray/bluray.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 124 insertions(+), 4 deletions(-)
diff --git a/src/libbluray/bluray.c b/src/libbluray/bluray.c
index 97e84b7..426d9a1 100644
--- a/src/libbluray/bluray.c
+++ b/src/libbluray/bluray.c
@@ -126,6 +126,7 @@ struct bluray {
/* streams */
BD_STREAM st0; /* main path */
BD_PRELOAD st_ig; /* preloaded IG stream sub path */
+ BD_PRELOAD st_textst; /* preloaded TextST sub path */
int ig_pid; /* pid of currently selected IG stream in main path */
int pg_pid; /* pid of currently selected PG stream in main path */
@@ -172,6 +173,10 @@ struct bluray {
uint32_t gc_status;
uint8_t decode_pg;
+ /* TextST */
+ uint32_t gc_wakeup_time; /* stream timestamp of next subtitle */
+ uint64_t gc_wakeup_pos; /* stream position of gc_wakeup_time */
+
/* ARGB overlay output */
void *argb_overlay_proc_handle;
bd_argb_overlay_proc_f argb_overlay_proc;
@@ -390,7 +395,7 @@ static void _update_chapter_psr(BLURAY *bd)
* PG
*/
-static int _find_pg_stream(BLURAY *bd, uint16_t *pid, int *sub_path_idx)
+static int _find_pg_stream(BLURAY *bd, uint16_t *pid, int *sub_path_idx, bd_char_code_e *char_code)
{
MPLS_PI *pi = &bd->title->pl->play_item[0];
unsigned pg_stream = bd_psr_read(bd->regs, PSR_PG_STREAM);
@@ -409,6 +414,10 @@ static int _find_pg_stream(BLURAY *bd, uint16_t *pid, int *sub_path_idx)
}
*pid = pi->stn.pg[pg_stream].pid;
+ if (char_code && pi->stn.pg[pg_stream].coding_type == BLURAY_STREAM_TYPE_SUB_TEXT) {
+ *char_code = pi->stn.pg[pg_stream].char_code;
+ }
+
BD_DEBUG(DBG_BLURAY, "_find_pg_stream(): current PG stream pid 0x%04x sub-path %d\n",
*pid, *sub_path_idx);
return 1;
@@ -435,7 +444,7 @@ static int _init_pg_stream(BLURAY *bd)
return 0;
}
- _find_pg_stream(bd, &pg_pid, &pg_subpath);
+ _find_pg_stream(bd, &pg_pid, &pg_subpath, NULL);
/* store PID of main path embedded IG stream */
if (pg_subpath < 0) {
@@ -446,6 +455,40 @@ static int _init_pg_stream(BLURAY *bd)
return 0;
}
+static void _update_textst_timer(BLURAY *bd)
+{
+ if (bd->st_textst.clip) {
+ if (bd->s_pos >= bd->gc_wakeup_pos) {
+ GC_NAV_CMDS cmds = {-1, NULL, -1, 0, 0};
+
+ gc_run(bd->graphics_controller, GC_CTRL_PG_UPDATE, bd->gc_wakeup_time, &cmds);
+
+ bd->gc_wakeup_time = cmds.wakeup_time;
+ bd->gc_wakeup_pos = (uint64_t)(int64_t)-1; /* no wakeup */
+
+ /* next event in this clip ? */
+ if (cmds.wakeup_time >= bd->st0.clip->in_time && cmds.wakeup_time < bd->st0.clip->out_time) {
+ /* find event position in main path clip */
+ NAV_CLIP *clip = bd->st0.clip;
+ uint32_t spn = clpi_lookup_spn(clip->cl, cmds.wakeup_time, 1,
+ bd->title->pl->play_item[clip->ref].clip[clip->angle].stc_id);
+ if (spn) {
+ bd->gc_wakeup_pos = spn * 192;
+ }
+ }
+ }
+ }
+}
+
+static void _init_textst_timer(BLURAY *bd)
+{
+ if (bd->st_textst.clip) {
+ bd->gc_wakeup_time = (uint32_t)(bd_tell_time(bd) >> 1);
+ bd->gc_wakeup_pos = 0;
+ _update_textst_timer(bd);
+ }
+}
+
/*
* clip access (BD_STREAM)
*/
@@ -499,6 +542,8 @@ static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
_update_clip_psrs(bd, st->clip);
_init_pg_stream(bd);
+
+ _init_textst_timer(bd);
}
return 1;
@@ -694,7 +739,7 @@ static int _run_gc(BLURAY *bd, gc_ctrl_e msg, uint32_t param)
int result = -1;
if (bd && bd->graphics_controller && bd->hdmv_vm) {
- GC_NAV_CMDS cmds = {-1, NULL, -1, 0};
+ GC_NAV_CMDS cmds = {-1, NULL, -1, 0, 0};
result = gc_run(bd->graphics_controller, msg, param, &cmds);
@@ -1399,6 +1444,7 @@ void bd_close(BLURAY *bd)
_close_m2ts(&bd->st0);
_close_preload(&bd->st_ig);
+ _close_preload(&bd->st_textst);
if (bd->title_list != NULL) {
nav_free_title_list(bd->title_list);
@@ -1487,6 +1533,8 @@ static void _seek_internal(BLURAY *bd,
/* reset PG decoder and controller */
if (bd->graphics_controller) {
gc_run(bd->graphics_controller, GC_CTRL_PG_RESET, 0, NULL);
+
+ _init_textst_timer(bd);
}
BD_DEBUG(DBG_BLURAY, "Seek to %"PRIu64"\n", bd->s_pos);
@@ -1836,6 +1884,9 @@ static int _bd_read(BLURAY *bd, unsigned char *buf, int len)
gc_run(bd->graphics_controller, GC_CTRL_PG_UPDATE, 0, NULL);
}
}
+ if (bd->st_textst.clip) {
+ _update_textst_timer(bd);
+ }
st->int_buf_off = st->clip_pos % 6144;
@@ -1917,6 +1968,60 @@ int bd_read_skip_still(BLURAY *bd)
}
/*
+ * synchronous sub paths
+ */
+
+static int _preload_textst_subpath(BLURAY *bd)
+{
+ bd_char_code_e char_code = BLURAY_TEXT_CHAR_CODE_UTF8;
+ int textst_subpath = -1;
+ uint16_t textst_pid = 0;
+ unsigned ii;
+
+ if (!bd->graphics_controller) {
+ return 0;
+ }
+
+ _find_pg_stream(bd, &textst_pid, &textst_subpath, &char_code);
+ if (textst_subpath < 0) {
+ return 0;
+ }
+
+ if (bd->st_textst.clip == &bd->title->sub_path[textst_subpath].clip_list.clip[0]) {
+ BD_DEBUG(DBG_STREAM, "_preload_textst_subpath(): subpath already loaded");
+ return 1;
+ }
+
+ gc_run(bd->graphics_controller, GC_CTRL_PG_RESET, 0, NULL);
+
+ bd->st_textst.clip = &bd->title->sub_path[textst_subpath].clip_list.clip[0];
+ if (bd->title->sub_path[textst_subpath].clip_list.count > 1) {
+ BD_DEBUG(DBG_STREAM | DBG_CRIT, "_preload_textst_subpath(): multi-clip sub paths not supported\n");
+ }
+
+ if (!_preload_m2ts(bd, &bd->st_textst)) {
+ _close_preload(&bd->st_textst);
+ return 0;
+ }
+
+ gc_decode_ts(bd->graphics_controller, 0x1800, bd->st_textst.buf, SPN(bd->st_textst.clip_size) / 32, -1);
+
+ /* set fonts and encoding from clip info */
+ gc_add_font(bd->graphics_controller, NULL);
+ for (ii = 0; ii < bd->st_textst.clip->cl->font_info.font_count; ii++) {
+ char *file = str_printf("%s/BDMV/AUXDATA/%s.otf", bd->device_path, bd->st_textst.clip->cl->font_info.font[ii].file_id);
+ gc_add_font(bd->graphics_controller, file);
+ X_FREE(file);
+ }
+ gc_run(bd->graphics_controller, GC_CTRL_PG_CHARCODE, char_code, NULL);
+
+ /* start presentation timer */
+ _init_textst_timer(bd);
+
+ return 1;
+}
+
+/*
* preloader for asynchronous sub paths
*/
@@ -1955,8 +2060,17 @@ static int _preload_ig_subpath(BLURAY *bd)
return 0;
}
+ if (bd->st_ig.clip == &bd->title->sub_path[ig_subpath].clip_list.clip[0]) {
+ BD_DEBUG(DBG_STREAM | DBG_CRIT, "_preload_ig_subpath(): subpath already loaded");
+ //return 1;
+ }
+
bd->st_ig.clip = &bd->title->sub_path[ig_subpath].clip_list.clip[0];
+ if (bd->title->sub_path[ig_subpath].clip_list.count > 1) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "_preload_ig_subpath(): multi-clip sub paths not supported\n");
+ }
+
if (!_preload_m2ts(bd, &bd->st_ig)) {
_close_preload(&bd->st_ig);
return 0;
@@ -1968,12 +2082,13 @@ static int _preload_ig_subpath(BLURAY *bd)
static int _preload_subpaths(BLURAY *bd)
{
_close_preload(&bd->st_ig);
+ _close_preload(&bd->st_textst);
if (bd->title->pl->sub_count <= 0) {
return 0;
}
- return _preload_ig_subpath(bd);
+ return _preload_ig_subpath(bd) | _preload_textst_subpath(bd);
}
static int _init_ig_stream(BLURAY *bd)
@@ -2016,6 +2131,7 @@ static void _close_playlist(BLURAY *bd)
_close_m2ts(&bd->st0);
_close_preload(&bd->st_ig);
+ _close_preload(&bd->st_textst);
if (bd->title) {
nav_title_close(bd->title);
@@ -2571,6 +2687,10 @@ static void _process_psr_change_event(BLURAY *bd, BD_PSR_EVENT *ev)
bd_mutex_lock(&bd->mutex);
_init_pg_stream(bd);
+ if (bd->st_textst.clip) {
+ BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Changing TextST stream\n");
+ _preload_textst_subpath(bd);
+ }
bd_mutex_unlock(&bd->mutex);
break;
More information about the libbluray-devel
mailing list