Commit 6ad01ebf authored by j45's avatar j45

add seamless angle change support and fix offsets to bdplus_seek

to initiate a seamless angle change:
void bd_seamless_angle_change(BLURAY *bd, int angle);
parent 36db542d
......@@ -235,11 +235,57 @@ int _read_block(BLURAY *bd)
return 0;
}
int64_t bd_seek_time(BLURAY *bd, uint64_t tick)
{
uint32_t clip_pkt, out_pkt;
NAV_CLIP *clip;
if (bd->seamless_angle_change) {
bd->clip = nav_set_angle(bd->title, bd->clip, bd->request_angle);
bd->angle = bd->request_angle;
bd->seamless_angle_change = 0;
}
if (tick < bd->title->duration) {
tick /= 2;
// Find the closest access unit to the requested position
clip = nav_time_search(bd->title, tick, &clip_pkt, &out_pkt);
if (clip->ref != bd->clip->ref) {
// The position is in a new clip
bd->clip = clip;
if (!_open_m2ts(bd)) {
return -1;
}
}
bd->s_pos = (uint64_t)out_pkt * 192;
bd->clip_pos = (uint64_t)clip_pkt * 192;
bd->clip_block_pos = (bd->clip_pos / 6144) * 6144;
file_seek(bd->fp, bd->clip_block_pos, SEEK_SET);
bd->int_buf_off = 6144;
DEBUG(DBG_BLURAY, "Seek to %"PRIu64" (%p)\n",
bd->s_pos, bd);
if (bd->bdplus_seek && bd->bdplus)
bd->bdplus_seek(bd->bdplus, bd->clip_block_pos);
return bd->s_pos;
}
return bd->s_pos;
}
int64_t bd_seek(BLURAY *bd, uint64_t pos)
{
uint32_t pkt, clip_pkt, out_pkt, out_time;
NAV_CLIP *clip;
if (bd->seamless_angle_change) {
bd->clip = nav_set_angle(bd->title, bd->clip, bd->request_angle);
bd->angle = bd->request_angle;
bd->seamless_angle_change = 0;
}
if (pos < bd->s_size) {
pkt = pos / 192;
......@@ -263,7 +309,34 @@ int64_t bd_seek(BLURAY *bd, uint64_t pos)
DEBUG(DBG_BLURAY, "Seek to %"PRIu64" (%p)\n",
bd->s_pos, bd);
if (bd->bdplus_seek && bd->bdplus)
bd->bdplus_seek(bd->bdplus, bd->s_pos);
bd->bdplus_seek(bd->bdplus, bd->clip_block_pos);
return bd->s_pos;
}
return bd->s_pos;
}
static int64_t _clip_seek_time(BLURAY *bd, uint64_t tick)
{
uint32_t clip_pkt, out_pkt;
if (tick < bd->clip->out_time) {
// Find the closest access unit to the requested position
nav_clip_time_search(bd->clip, tick, &clip_pkt, &out_pkt);
bd->s_pos = (uint64_t)out_pkt * 192;
bd->clip_pos = (uint64_t)clip_pkt * 192;
bd->clip_block_pos = (bd->clip_pos / 6144) * 6144;
file_seek(bd->fp, bd->clip_block_pos, SEEK_SET);
bd->int_buf_off = 6144;
DEBUG(DBG_BLURAY, "Clip seek to %"PRIu64" (%p)\n",
bd->s_pos, bd);
if (bd->bdplus_seek && bd->bdplus)
bd->bdplus_seek(bd->bdplus, bd->clip_block_pos);
return bd->s_pos;
}
......@@ -283,8 +356,33 @@ int bd_read(BLURAY *bd, unsigned char *buf, int len)
while (len > 0) {
uint32_t clip_pkt;
size = len;
// Do we need to read more data?
clip_pkt = bd->clip_pos / 192;
if (bd->seamless_angle_change) {
if (clip_pkt >= bd->angle_change_pkt) {
if (clip_pkt >= bd->clip->end_pkt) {
bd->clip = nav_next_clip(bd->title, bd->clip);
if (!_open_m2ts(bd)) {
return -1;
}
bd->s_pos = bd->clip->pos;
} else {
bd->clip = nav_set_angle(bd->title, bd->clip, bd->request_angle);
_clip_seek_time(bd, bd->angle_change_time);
}
bd->angle = bd->request_angle;
bd->seamless_angle_change = 0;
} else {
int64_t angle_pos;
angle_pos = (int64_t)bd->angle_change_pkt * 192;
if (angle_pos - bd->clip_pos < size)
{
size = angle_pos - bd->clip_pos;
}
}
}
if (bd->int_buf_off == 6144 || clip_pkt >= bd->clip->end_pkt) {
// Do we need to get the next clip?
......@@ -306,10 +404,8 @@ int bd_read(BLURAY *bd, unsigned char *buf, int len)
return out_len;
}
}
if (len > 6144 - bd->int_buf_off) {
if (size > 6144 - bd->int_buf_off) {
size = 6144 - bd->int_buf_off;
} else {
size = len;
}
memcpy(buf, bd->int_buf + bd->int_buf_off, size);
buf += size;
......@@ -354,6 +450,8 @@ int bd_select_title(BLURAY *bd, uint32_t title_idx)
return 0;
}
bd->angle = 0;
bd->seamless_angle_change = 0;
bd->s_pos = 0;
bd->s_size = (uint64_t)bd->title->packets * 192;
......@@ -376,6 +474,17 @@ int bd_select_angle(BLURAY *bd, int angle)
return 1;
}
void bd_seamless_angle_change(BLURAY *bd, int angle)
{
uint32_t clip_pkt;
clip_pkt = (bd->clip_pos + 191) / 192;
bd->angle_change_pkt = nav_angle_change_search(bd->clip, clip_pkt,
&bd->angle_change_time);
bd->request_angle = angle;
bd->seamless_angle_change = 1;
}
uint64_t bd_get_title_size(BLURAY *bd)
{
return bd ? bd->s_size : UINT64_C(0);
......
......@@ -31,6 +31,11 @@ struct bluray {
fptr_int libaacs_decrypt_unit;
uint8_t int_buf[6144];
uint16_t int_buf_off;
int seamless_angle_change;
uint32_t angle_change_pkt;
uint32_t angle_change_time;
int request_angle;
int angle;
};
typedef struct bd_chapter {
......@@ -56,10 +61,12 @@ BLURAY *bd_open(const char* device_path, const char* keyfile_path); // Init libb
void bd_close(BLURAY *bd); // Free libbluray objs
int64_t bd_seek(BLURAY *bd, uint64_t pos); // Seek to pos in currently selected title file
int64_t bd_seek_time(BLURAY *bd, uint64_t tick); // Seek to a specific time in 90Khz ticks
int bd_read(BLURAY *bd, unsigned char *buf, int len); // Read from currently selected title file, decrypt if possible
int bd_select_title(BLURAY *bd, uint32_t title); // Select the title from the list created by bd_get_titles()
int bd_select_angle(BLURAY *bd, int angle); // Set the angle to play
void bd_seamless_angle_change(BLURAY *bd, int angle); // Initiate seamless angle change
uint64_t bd_get_title_size(BLURAY *bd); // Returns file size in bytes of currently selected title, 0 in no title selected
uint64_t bd_tell(BLURAY *bd); // Return current pos
......
......@@ -332,6 +332,8 @@ NAV_TITLE* nav_title_open(char *root, char *playlist)
NAV_TITLE *title = NULL;
char *path;
int ii, chapters = 0;
uint32_t pos = 0;
uint32_t time = 0;
title = calloc(1, sizeof(NAV_TITLE));
if (title == NULL) {
......@@ -363,6 +365,8 @@ NAV_TITLE* nav_title_open(char *root, char *playlist)
pi = &title->pl->play_item[ii];
clip = &title->clip_list.clip[ii];
clip->title = title;
clip->ref = ii;
clip->angle = 0;
strncpy(clip->name, pi->clip[clip->angle].clip_id, 5);
......@@ -392,6 +396,12 @@ NAV_TITLE* nav_title_open(char *root, char *playlist)
}
clip->end_pkt = clpi_lookup_spn(clip->cl, pi->out_time, 0,
pi->clip[clip->angle].stc_id);
clip->in_time = pi->in_time;
clip->out_time = pi->out_time;
clip->pos = pos;
pos += clip->end_pkt - clip->start_pkt;
clip->start_time = time;
time += clip->out_time - clip->in_time;
}
// Count the number of "entry" marks (skipping "link" marks)
// This is the the number of chapters
......@@ -457,8 +467,7 @@ NAV_CLIP* nav_packet_search(NAV_TITLE *title, uint32_t pkt, uint32_t *clip_pkt,
clip = &title->clip_list.clip[ii];
*clip_pkt = clpi_access_point(clip->cl, pkt - pos + clip->start_pkt, 0, 0, out_time);
}
pos += *clip_pkt - clip->start_pkt;
*out_pkt = pos;
*out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
return clip;
}
......@@ -480,8 +489,9 @@ NAV_CLIP* nav_packet_search(NAV_TITLE *title, uint32_t pkt, uint32_t *clip_pkt,
// from nav_set_angle.
// 4. If the angle change point was within the time period of the current
// play item (i.e. the angle change point is not at the end of the clip),
// Search to the timestamp obtained from nav_angle_change using
// nav_time_search. Otherwise start at the start_pkt defined by the clip.
// Search to the timestamp obtained from nav_angle_change_search using
// nav_clip_time_search. Otherwise start at the start_pkt defined
// by the clip.
uint32_t nav_angle_change_search(NAV_CLIP *clip, uint32_t pkt, uint32_t *time)
{
return clpi_access_point(clip->cl, pkt, 1, 1, time);
......@@ -489,7 +499,7 @@ uint32_t nav_angle_change_search(NAV_CLIP *clip, uint32_t pkt, uint32_t *time)
// Search for random access point closest to the requested time
// Time is in 45khz ticks
NAV_CLIP* nav_time_search(NAV_TITLE *title, uint32_t tick, uint32_t *out_pkt)
NAV_CLIP* nav_time_search(NAV_TITLE *title, uint32_t tick, uint32_t *clip_pkt, uint32_t *out_pkt)
{
uint32_t pos, len;
MPLS_PI *pi;
......@@ -506,12 +516,27 @@ NAV_CLIP* nav_time_search(NAV_TITLE *title, uint32_t tick, uint32_t *out_pkt)
}
if (ii == title->pl->list_count) {
clip = &title->clip_list.clip[ii-1];
*out_pkt = clip->end_pkt;
*clip_pkt = clip->end_pkt;
} else {
clip = &title->clip_list.clip[ii];
*out_pkt = clpi_lookup_spn(clip->cl, tick - pos + pi->in_time, 1,
*clip_pkt = clpi_lookup_spn(clip->cl, tick - pos + pi->in_time, 1,
title->pl->play_item[clip->ref].clip[clip->angle].stc_id);
}
*out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
return clip;
}
// Search for random access point closest to the requested time
// Time is in 45khz ticks relative to the beginning of a specific clip
void nav_clip_time_search(NAV_CLIP *clip, uint32_t tick, uint32_t *clip_pkt, uint32_t *out_pkt)
{
if (tick >= clip->out_time) {
*out_pkt = clip->end_pkt;
} else {
*clip_pkt = clpi_lookup_spn(clip->cl, tick, 1,
clip->title->pl->play_item[clip->ref].clip[clip->angle].stc_id);
}
*out_pkt = clip->pos + *clip_pkt - clip->start_pkt;
return clip;
}
......@@ -538,6 +563,8 @@ NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, int angle)
{
char *path;
int ii;
uint32_t pos = 0;
uint32_t time = 0;
if (title == NULL) {
return clip;
......@@ -591,6 +618,12 @@ NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, int angle)
}
clip->end_pkt = clpi_lookup_spn(clip->cl, pi->out_time, 0,
pi->clip[clip->angle].stc_id);
clip->in_time = pi->in_time;
clip->out_time = pi->out_time;
clip->pos = pos;
pos += clip->end_pkt - clip->start_pkt;
clip->start_time = time;
time += clip->out_time - clip->in_time;
}
_extrapolate_title(title);
return clip;
......
......@@ -13,6 +13,8 @@
#define TITLES_FILTER_DUP_CLIP 0x02
#define TITLES_RELEVANT (TITLES_FILTER_DUP_TITLE | TITLES_FILTER_DUP_CLIP)
typedef struct nav_title_s NAV_TITLE;
typedef struct {
int number;
int clip_ref;
......@@ -35,17 +37,24 @@ typedef struct {
char name[11];
uint32_t clip_id;
int ref;
uint32_t pos;
uint32_t start_pkt;
uint32_t end_pkt;
uint8_t connection;
uint8_t angle;
uint32_t start_time;
uint32_t duration;
uint32_t in_time;
uint32_t out_time;
// Title relative metrics
uint32_t title_pkt;
uint32_t title_time;
NAV_TITLE *title;
CLPI_CL *cl;
} NAV_CLIP;
......@@ -54,7 +63,7 @@ typedef struct {
NAV_CLIP *clip;
} NAV_CLIP_LIST;
typedef struct {
struct nav_title_s {
char *root;
char name[11];
uint8_t angle_count;
......@@ -66,7 +75,7 @@ typedef struct {
uint32_t duration;
MPLS_PL *pl;
} NAV_TITLE;
};
typedef struct {
char name[11];
......@@ -85,7 +94,8 @@ NAV_TITLE* nav_title_open(char *root, char *playlist);
void nav_title_close(NAV_TITLE *title);
NAV_CLIP* nav_next_clip(NAV_TITLE *title, NAV_CLIP *clip);
NAV_CLIP* nav_packet_search(NAV_TITLE *title, uint32_t pkt, uint32_t *clip_pkt, uint32_t *out_pkt, uint32_t *out_time);
NAV_CLIP* nav_time_search(NAV_TITLE *title, uint32_t tick, uint32_t *out_pkt);
NAV_CLIP* nav_time_search(NAV_TITLE *title, uint32_t tick, uint32_t *clip_pkt, uint32_t *out_pkt);
void nav_clip_time_search(NAV_CLIP *clip, uint32_t tick, uint32_t *clip_pkt, uint32_t *out_pkt);
NAV_CLIP* nav_chapter_search(NAV_TITLE *title, int chapter, uint32_t *out_pkt);
uint32_t nav_angle_change_search(NAV_CLIP *clip, uint32_t pkt, uint32_t *time);
NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, int angle);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment