libbluray | branch: master | hpi1 <[email protected]> | Wed Apr 22 13:52:04 2015 +0300| [f8de9a561108acb3ddc237789f55c682099d58f8] | committer: hpi1
HDMV: support state serialization and restore > http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=f8de9a561108acb3ddc237789f55c682099d58f8 --- src/libbluray/hdmv/hdmv_vm.c | 86 ++++++++++++++++++++++++++++++++++++++++++ src/libbluray/hdmv/hdmv_vm.h | 11 ++++++ src/libbluray/register.c | 51 +++++++++++++++++++++++++ src/libbluray/register.h | 9 +++++ 4 files changed, 157 insertions(+) diff --git a/src/libbluray/hdmv/hdmv_vm.c b/src/libbluray/hdmv/hdmv_vm.c index 2fb99b1..6583562 100644 --- a/src/libbluray/hdmv/hdmv_vm.c +++ b/src/libbluray/hdmv/hdmv_vm.c @@ -72,6 +72,92 @@ struct hdmv_vm_s { }; /* + * save / restore VM state + */ + +static int _save_state(HDMV_VM *p, uint32_t *s) +{ + memset(s, 0, sizeof(*s) * HDMV_STATE_SIZE); + + if (p->ig_object) { + BD_DEBUG(DBG_HDMV | DBG_CRIT, "_save_state() failed: button object running\n"); + return -1; + } + if (p->object) { + BD_DEBUG(DBG_HDMV | DBG_CRIT, "_save_state() failed: movie object running\n"); + return -1; + } + if (p->event[0].event != HDMV_EVENT_NONE) { + BD_DEBUG(DBG_HDMV | DBG_CRIT, "_save_state() failed: unprocessed events\n"); + return -1; + } + + if (p->playing_object) { + s[0] = (uint32_t)(p->playing_object - p->movie_objects->objects); + s[1] = p->playing_pc; + } else { + s[0] = (uint32_t)-1; + } + + if (p->suspended_object) { + s[2] = (uint32_t)(p->suspended_object - p->movie_objects->objects); + s[3] = p->suspended_pc; + } else { + s[2] = (uint32_t)-1; + } + + /* nv timer ? */ + + return 0; +} + +static int _restore_state(HDMV_VM *p, const uint32_t *s) +{ + if (s[0] == (uint32_t)-1) { + p->playing_object = NULL; + } else if (s[0] >= p->movie_objects->num_objects) { + BD_DEBUG(DBG_HDMV | DBG_CRIT, "_restore_state() failed: invalid playing object index\n"); + return -1; + } else { + p->playing_object = &p->movie_objects->objects[s[0]]; + } + p->playing_pc = s[1]; + + if (s[2] == (uint32_t)-1) { + p->suspended_object = NULL; + } else if (s[2] >= p->movie_objects->num_objects) { + BD_DEBUG(DBG_HDMV | DBG_CRIT, "_restore_state() failed: invalid suspended object index\n"); + return -1; + } else { + p->suspended_object = &p->movie_objects->objects[s[2]]; + } + p->suspended_pc = s[3]; + + p->object = NULL; + p->ig_object = NULL; + memset(p->event, 0, sizeof(p->event)); + + return 0; +} + +int hdmv_vm_save_state(HDMV_VM *p, uint32_t *s) +{ + int result; + bd_mutex_lock(&p->mutex); + result = _save_state(p, s); + bd_mutex_unlock(&p->mutex); + return result; +} + +void hdmv_vm_restore_state(HDMV_VM *p, const uint32_t *s) +{ + bd_mutex_lock(&p->mutex); + _restore_state(p, s); + bd_mutex_unlock(&p->mutex); +} + + +/* * registers: PSR and GPR access */ diff --git a/src/libbluray/hdmv/hdmv_vm.h b/src/libbluray/hdmv/hdmv_vm.h index 06ea2ed..c7d95f1 100644 --- a/src/libbluray/hdmv/hdmv_vm.h +++ b/src/libbluray/hdmv/hdmv_vm.h @@ -119,4 +119,15 @@ BD_PRIVATE int hdmv_vm_suspend_pl(HDMV_VM *p); */ BD_PRIVATE int hdmv_vm_resume(HDMV_VM *p); + +/* + * save / restore VM state + */ + +/* VM state size */ +#define HDMV_STATE_SIZE 10 /* * sizeof(uint32_t) */ + +BD_PRIVATE int hdmv_vm_save_state(HDMV_VM *p, uint32_t *s); +BD_PRIVATE void hdmv_vm_restore_state(HDMV_VM *p, const uint32_t *s); + #endif // _HDMV_VM_H_ diff --git a/src/libbluray/register.c b/src/libbluray/register.c index 964933e..0e20496 100644 --- a/src/libbluray/register.c +++ b/src/libbluray/register.c @@ -475,3 +475,54 @@ int bd_psr_write_bits(BD_REGISTERS *p, int reg, uint32_t val, uint32_t mask) return result; } + +/* + * save / restore registers between playback sessions + */ + +void registers_save(BD_REGISTERS *p, uint32_t *psr, uint32_t *gpr) +{ + bd_psr_lock(p); + + memcpy(gpr, p->gpr, sizeof(p->gpr)); + memcpy(psr, p->psr, sizeof(p->psr)); + + bd_psr_unlock(p); +} + +void registers_restore(BD_REGISTERS *p, const uint32_t *psr, const uint32_t *gpr) +{ + uint32_t new_psr[13]; + + bd_psr_lock(p); + + memcpy(p->gpr, gpr, sizeof(p->gpr)); + memcpy(p->psr, psr, sizeof(p->psr)); + + memcpy(new_psr, p->psr, sizeof(new_psr[0]) * 13); + + /* generate restore events */ + if (p->num_cb) { + BD_PSR_EVENT ev; + unsigned i, j; + + ev.ev_type = BD_PSR_RESTORE; + ev.old_val = 0; /* not used with BD_PSR_RESTORE */ + + for (i = 4; i < 13; i++) { + if (i != PSR_NAV_TIMER) { + + p->psr[i] = new_psr[i]; + + ev.psr_idx = i; + ev.new_val = new_psr[i]; + + for (j = 0; j < p->num_cb; j++) { + p->cb[j].cb(p->cb[j].handle, &ev); + } + } + } + } + + bd_psr_unlock(p); +} diff --git a/src/libbluray/register.h b/src/libbluray/register.h index 3e564ff..c936aca 100644 --- a/src/libbluray/register.h +++ b/src/libbluray/register.h @@ -264,4 +264,13 @@ void bd_psr_register_cb(BD_REGISTERS *, void (*callback)(void*,BD_PSR_EVENT*), v void bd_psr_unregister_cb(BD_REGISTERS *, void (*callback)(void*,BD_PSR_EVENT*), void *cb_handle); +/* + * save / restore registers between playback sessions + * + * When state is restored, restore events will be generated and playback state is restored. + */ + +BD_PRIVATE void registers_save(BD_REGISTERS *p, uint32_t *psr, uint32_t *gpr); +BD_PRIVATE void registers_restore(BD_REGISTERS *p, const uint32_t *psr, const uint32_t *gpr); + #endif /* _BD_REGISTER_H_ */ _______________________________________________ libbluray-devel mailing list [email protected] https://mailman.videolan.org/listinfo/libbluray-devel
