int BDRingBuffer::safe_read(void *data, uint sz) { int result = 0; if (m_isHDMVNavigation) { HandleBDEvents(); while (result == 0) { BD_EVENT event; result = bd_read_ext(bdnav, (unsigned char *)data, sz, &event); HandleBDEvent(event); if (result == 0) HandleBDEvents(); } } else { result = bd_read(bdnav, (unsigned char *)data, sz); } m_currentTime = bd_tell_time(bdnav); return result; }
static int bluray_stream_control(stream_t *s, int cmd, void *arg) { struct bluray_priv_s *b = s->priv; switch (cmd) { case STREAM_CTRL_GET_NUM_CHAPTERS: { BLURAY_TITLE_INFO *ti; ti = bd_get_title_info(b->bd, b->current_title, b->current_angle); if (!ti) return STREAM_UNSUPPORTED; *((unsigned int *) arg) = ti->chapter_count; bd_free_title_info(ti); return 1; } case STREAM_CTRL_GET_CURRENT_TITLE: { *((unsigned int *) arg) = b->current_title; return 1; } case STREAM_CTRL_GET_CURRENT_CHAPTER: { *((unsigned int *) arg) = bd_get_current_chapter(b->bd); return 1; } case STREAM_CTRL_SEEK_TO_CHAPTER: { BLURAY_TITLE_INFO *ti; int chapter = *((unsigned int *) arg); int64_t pos; int r; ti = bd_get_title_info(b->bd, b->current_title, b->current_angle); if (!ti) return STREAM_UNSUPPORTED; if (chapter < 0 || chapter > ti->chapter_count) { bd_free_title_info(ti); return STREAM_UNSUPPORTED; } pos = bd_chapter_pos(b->bd, chapter); r = bluray_stream_seek(s, pos); bd_free_title_info(ti); return r ? 1 : STREAM_UNSUPPORTED; } case STREAM_CTRL_GET_TIME_LENGTH: { BLURAY_TITLE_INFO *ti = bd_get_title_info(b->bd, b->current_title, b->current_angle); if (!ti) return STREAM_UNSUPPORTED; *(double *)arg = ti->duration / 90000.0; return STREAM_OK; } case STREAM_CTRL_GET_SIZE: *(uint64_t*)arg = bd_get_title_size(b->bd); return STREAM_OK; case STREAM_CTRL_GET_CURRENT_TIME: *(double *)arg = bd_tell_time(b->bd) / 90000.0; return STREAM_OK; case STREAM_CTRL_SEEK_TO_TIME: { int64_t res; double target = *(double*)arg * 90000.0; BLURAY_TITLE_INFO *ti = bd_get_title_info(b->bd, b->current_title, b->current_angle); // clamp to ensure that out-of-bounds seeks do not simply do nothing. target = FFMAX(target, 0); if (ti && ti->duration > 1) target = FFMIN(target, ti->duration - 1); res = bd_seek_time(b->bd, target); if (res < 0) return STREAM_ERROR; s->pos = res; return 1; } case STREAM_CTRL_GET_NUM_ANGLES: { BLURAY_TITLE_INFO *ti; ti = bd_get_title_info(b->bd, b->current_title, b->current_angle); if (!ti) return STREAM_UNSUPPORTED; *((int *) arg) = ti->angle_count; bd_free_title_info(ti); return 1; } case STREAM_CTRL_GET_ANGLE: { *((int *) arg) = b->current_angle; return 1; } case STREAM_CTRL_SET_ANGLE: { BLURAY_TITLE_INFO *ti; int angle = *((int *) arg); ti = bd_get_title_info(b->bd, b->current_title, b->current_angle); if (!ti) return STREAM_UNSUPPORTED; if (angle < 0 || angle > ti->angle_count) { bd_free_title_info(ti); return STREAM_UNSUPPORTED; } b->current_angle = angle; bd_seamless_angle_change(b->bd, angle); bd_free_title_info(ti); return 1; } case STREAM_CTRL_GET_LANG: { struct stream_lang_req *req = arg; const BLURAY_STREAM_INFO *si; int count; BLURAY_TITLE_INFO *ti = get_langs(b, req->type, &si, &count); while (count-- > 0) { if (si->pid == req->id) { memcpy(req->buf, si->lang, 4); req->buf[4] = 0; bd_free_title_info(ti); return STREAM_OK; } si++; } if (ti) bd_free_title_info(ti); return STREAM_ERROR; } default: break; } return STREAM_UNSUPPORTED; }
JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellTimeN(JNIEnv * env, jclass cls, jlong np) { BLURAY* bd = (BLURAY*)(intptr_t)np; return bd_tell_time(bd); }
long long BDRingBuffer::SeekInternal(long long pos, int whence) { long long ret = -1; poslock.lockForWrite(); // Optimize no-op seeks if (readaheadrunning && ((whence == SEEK_SET && pos == readpos) || (whence == SEEK_CUR && pos == 0))) { ret = readpos; poslock.unlock(); return ret; } // only valid for SEEK_SET & SEEK_CUR long long new_pos = (SEEK_SET==whence) ? pos : readpos + pos; // Here we perform a normal seek. When successful we // need to call ResetReadAhead(). A reset means we will // need to refill the buffer, which takes some time. if ((SEEK_END == whence) || ((SEEK_CUR == whence) && new_pos != 0)) { errno = EINVAL; ret = -1; } else { SeekInternal(new_pos); m_currentTime = bd_tell_time(bdnav); ret = new_pos; } if (ret >= 0) { readpos = ret; ignorereadpos = -1; if (readaheadrunning) ResetReadAhead(readpos); readAdjust = 0; } else { QString cmd = QString("Seek(%1, %2)").arg(pos) .arg((whence == SEEK_SET) ? "SEEK_SET" : ((whence == SEEK_CUR) ?"SEEK_CUR" : "SEEK_END")); LOG(VB_GENERAL, LOG_ERR, LOC + cmd + " Failed" + ENO); } poslock.unlock(); generalWait.wakeAll(); return ret; }