Esempio n. 1
0
STDMETHODIMP CBDDemuxer::SetTitle(int idx)
{
  HRESULT hr = S_OK;
  int ret; // return values
  if (m_pTitle) {
    bd_free_title_info(m_pTitle);
  }

  // Init Event Queue
  bd_get_event(m_pBD, nullptr);

  // Select title
  m_pTitle = bd_get_title_info(m_pBD, idx, 0);
  ret = bd_select_title(m_pBD, idx);
  if (ret == 0) {
    return E_FAIL;
  }

  if (m_pb) {
    av_free(m_pb->buffer);
    av_free(m_pb);
  }

  uint8_t *buffer = (uint8_t *)av_mallocz(BD_READ_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
  m_pb = avio_alloc_context(buffer, BD_READ_BUFFER_SIZE, 0, this, BDByteStreamRead, nullptr, BDByteStreamSeek);

  SafeRelease(&m_lavfDemuxer);
  SAFE_CO_FREE(m_rtOffset);

  m_lavfDemuxer = new CLAVFDemuxer(m_pLock, m_pSettings);
  m_lavfDemuxer->AddRef();
  m_lavfDemuxer->SetBluRay(this);
  if (FAILED(hr = m_lavfDemuxer->OpenInputStream(m_pb, nullptr, "mpegts", TRUE))) {
    SafeRelease(&m_lavfDemuxer);
    return hr;
  }

  m_lavfDemuxer->SeekByte(0, 0);

  // Process any events that occured during opening
  ProcessBDEvents();

  // Reset EOS protection
  m_EndOfStreamPacketFlushProtection = FALSE;

  // space for storing stream offsets
  m_rtOffset = (REFERENCE_TIME *)CoTaskMemAlloc(sizeof(REFERENCE_TIME) * m_lavfDemuxer->GetNumStreams());
  if (!m_rtOffset)
    return E_OUTOFMEMORY;
  memset(m_rtOffset, 0, sizeof(REFERENCE_TIME) * m_lavfDemuxer->GetNumStreams());

  DbgLog((LOG_TRACE, 20, L"Opened BD title with %d clips and %d chapters", m_pTitle->clip_count, m_pTitle->chapter_count));
  return S_OK;
}
Esempio n. 2
0
int BDRingBuffer::GetTitleDuration(int title) const
{
    int numTitles = GetNumTitles();

    if (!(numTitles > 0 && title >= 0 && title < numTitles))
        return 0;

    BLURAY_TITLE_INFO *info = bd_get_title_info(bdnav, title);
    if (!info)
        return 0;

    int duration = ((info->duration) / 90000.0f);
    bd_free_title_info(info);
    return duration;
}
Esempio n. 3
0
bool BDRingBuffer::SwitchTitle(uint32_t index)
{
    if (!bdnav)
        return false;

    if (m_currentTitleInfo)
        bd_free_title_info(m_currentTitleInfo);

    m_currentTitleInfo = bd_get_title_info(bdnav, index);

    if (!m_currentTitleInfo)
        return false;

    bd_select_title(bdnav, index);

    return UpdateTitleInfo(index);
}
Esempio n. 4
0
void CBlurayDirectory::GetTitles(bool main, CFileItemList &items)
{
  std::vector<BLURAY_TITLE_INFO*> titleList;
  uint64_t minDuration = 0;

  // Searching for a user provided list of playlists.
  if (main)
    titleList = GetUserPlaylists();

  if (!main || titleList.empty())
  {
    uint32_t numTitles = bd_get_titles(m_bd, TITLES_RELEVANT, 0);

    for (uint32_t i = 0; i < numTitles; i++)
    {
      BLURAY_TITLE_INFO* t = bd_get_title_info(m_bd, i, 0);

      if (!t)
      {
        CLog::Log(LOGDEBUG, "CBlurayDirectory - unable to get title %d", i);
        continue;
      }

      if (main && t->duration > minDuration)
          minDuration = t->duration;

      titleList.emplace_back(t);
    }
  }

  minDuration = minDuration * MAIN_TITLE_LENGTH_PERCENT / 100;

  for (auto& title : titleList)
  {
    if (title->duration < minDuration)
      continue;

    items.Add(GetTitle(title, main ? g_localizeStrings.Get(25004) /* Main Title */ : g_localizeStrings.Get(25005) /* Title */));
    bd_free_title_info(title);
  }
}
Esempio n. 5
0
BLURAY_TITLE_INFO* BDRingBuffer::GetTitleInfo(uint32_t index)
{
    if (!bdnav)
        return NULL;

    QMutexLocker locker(&m_infoLock);
    if (m_cachedTitleInfo.contains(index))
        return m_cachedTitleInfo.value(index);

    if (index > m_numTitles)
        return NULL;

    BLURAY_TITLE_INFO* result = bd_get_title_info(bdnav, index);
    if (result)
    {
        VERBOSE(VB_PLAYBACK, LOC + QString("Found title %1 info").arg(index));
        m_cachedTitleInfo.insert(index,result);
        return result;
    }
    return NULL;
}
Esempio n. 6
0
/***********************************************************************
 * hb_bd_init
 ***********************************************************************
 *
 **********************************************************************/
hb_bd_t * hb_bd_init( hb_handle_t *h, char * path )
{
    hb_bd_t * d;
    int ii;

    d = calloc( sizeof( hb_bd_t ), 1 );
    d->h = h;

    /* Open device */
    d->bd = bd_open( path, NULL );
    if( d->bd == NULL )
    {
        /*
         * Not an error, may be a stream - which we'll try in a moment.
         */
        hb_log( "bd: not a bd - trying as a stream/file instead" );
        goto fail;
    }

    d->title_count = bd_get_titles( d->bd, TITLES_RELEVANT, 0 );
    if ( d->title_count == 0 )
    {
        hb_log( "bd: not a bd - trying as a stream/file instead" );
        goto fail;
    }
    d->title_info = calloc( sizeof( BLURAY_TITLE_INFO* ) , d->title_count );
    for ( ii = 0; ii < d->title_count; ii++ )
    {
        d->title_info[ii] = bd_get_title_info( d->bd, ii, 0 );
    }
    qsort(d->title_info, d->title_count, sizeof( BLURAY_TITLE_INFO* ), title_info_compare_mpls );
    d->path = strdup( path );

    return d;

fail:
    if( d->bd ) bd_close( d->bd );
    free( d );
    return NULL;
}
Esempio n. 7
0
static BLURAY_TITLE_INFO *get_langs(const struct bluray_priv_s *b, enum stream_ctrl_type type,
                                    const BLURAY_STREAM_INFO **si, int *count)
{
    BLURAY_TITLE_INFO *ti = bd_get_title_info(b->bd, b->current_title, b->current_angle);
    *count = 0;
    if (ti->clip_count) {
        switch (type) {
        case stream_ctrl_audio:
            *count = ti->clips[0].audio_stream_count;
            *si = ti->clips[0].audio_streams;
            break;
        case stream_ctrl_sub:
            *count = ti->clips[0].pg_stream_count;
            *si = ti->clips[0].pg_streams;
            break;
        }
        if (*count > 0)
            return ti;
    }
    *si = NULL;
    bd_free_title_info(ti);
    return NULL;
}
Esempio n. 8
0
/////////////////////////////////////////////////////////////////////////////
// Demuxer Functions
STDMETHODIMP CBDDemuxer::Open(LPCOLESTR pszFileName)
{
  CAutoLock lock(m_pLock);
  HRESULT hr = S_OK;

  int ret; // return code from C functions

  // Convert the filename from wchar to char for libbluray
  char fileName[4096];
  ret = WideCharToMultiByte(CP_UTF8, 0, pszFileName, -1, fileName, 4096, nullptr, nullptr);

  int iPlaylist = -1;

  DbgLog((LOG_TRACE, 10, L"Initializing BluRay Demuxer; Entry Point: %s", pszFileName));

  size_t len = strlen(fileName);
  if (len > 16) {
    char *bd_path = fileName;
    if(_strcmpi(bd_path+strlen(bd_path) - 16, "\\BDMV\\index.bdmv") == 0) {
      bd_path[strlen(bd_path) - 15] = 0;
    } else if (len > 22 && _strcmpi(bd_path+strlen(bd_path) - 22, "\\BDMV\\MovieObject.bdmv") == 0) {
      bd_path[strlen(bd_path) - 21] = 0;
    } else if (len > 25 && _strnicmp(bd_path+strlen(bd_path) - 25, "\\BDMV\\PLAYLIST\\", 15) == 0) {
      char *playlist = &bd_path[strlen(bd_path) - 10];
      bd_path[strlen(bd_path) - 24] = 0;

      playlist[5] = 0;
      iPlaylist = atoi(playlist);
    } else {
      return E_FAIL;
    }
    // Open BluRay
    BLURAY *bd = bd_open(bd_path, nullptr);
    if(!bd) {
      return E_FAIL;
    }
    m_pBD = bd;

    uint32_t timelimit = (iPlaylist != -1) ? 0 : 180;
    uint8_t flags = (iPlaylist != -1) ? TITLES_ALL : TITLES_RELEVANT;

    // Fetch titles
fetchtitles:
    m_nTitleCount = bd_get_titles(bd, flags, timelimit);

    if (m_nTitleCount <= 0) {
      if (timelimit > 0) {
        timelimit = 0;
        goto fetchtitles;
      }
      if (flags != TITLES_ALL) {
        flags = TITLES_ALL;
        goto fetchtitles;
      }
      return E_FAIL;
    }

    DbgLog((LOG_TRACE, 20, L"Found %d titles", m_nTitleCount));
    DbgLog((LOG_TRACE, 20, L" ------ Begin Title Listing ------"));

    uint64_t longest_duration = 0;
    uint32_t title_id = 0;
    boolean found = false;
    for(uint32_t i = 0; i < m_nTitleCount; i++) {
      BLURAY_TITLE_INFO *info = bd_get_title_info(bd, i, 0);
      if (info) {
        DbgLog((LOG_TRACE, 20, L"Title %u, Playlist %u (%u clips, %u chapters), Duration %I64u (%I64u seconds)", i, info->playlist, info->clip_count, info->chapter_count, info->duration, Convert90KhzToDSTime(info->duration) / DSHOW_TIME_BASE));
        if (iPlaylist != -1 && info->playlist == iPlaylist) {
          title_id = i;
          found = true;
        } else if (iPlaylist == -1 && info->duration > longest_duration) {
          title_id = i;
          longest_duration = info->duration;
        }
        bd_free_title_info(info);
      }
      if (found)
        break;
    }
    DbgLog((LOG_TRACE, 20, L" ------ End Title Listing ------"));

    hr = SetTitle(title_id);
  }

  return hr;
}
Esempio n. 9
0
STDMETHODIMP CBDDemuxer::SetTitle(int idx)
{
  HRESULT hr = S_OK;
  int ret; // return values
  if (m_pTitle) {
    bd_free_title_info(m_pTitle);
  }

  // Init Event Queue
  bd_get_event(m_pBD, nullptr);

  // Select title
  m_pTitle = bd_get_title_info(m_pBD, idx, 0);
  ret = bd_select_title(m_pBD, idx);
  if (ret == 0) {
    return E_FAIL;
  }

  MPLS_PL * mpls = bd_get_title_mpls(m_pBD);
  if (mpls) {
    for (int i = 0; i < mpls->ext_sub_count; i++)
    {
      if (mpls->ext_sub_path[i].type == 8
        && mpls->ext_sub_path[i].sub_playitem_count == mpls->list_count)
      {
        DbgLog((LOG_TRACE, 20, L"CBDDemuxer::SetTitle(): Enabling BD3D MVC demuxing"));
        DbgLog((LOG_TRACE, 20, L" -> MVC_Base_view_R_flag: %d", m_pTitle->mvc_base_view_r_flag));
        m_MVCPlayback = TRUE;
        m_MVCExtensionSubPathIndex = i;
        break;
      }
    }
  }

  CloseMVCExtensionDemuxer();

  if (m_pb) {
    av_free(m_pb->buffer);
    av_free(m_pb);
  }

  uint8_t *buffer = (uint8_t *)av_mallocz(BD_READ_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
  m_pb = avio_alloc_context(buffer, BD_READ_BUFFER_SIZE, 0, this, BDByteStreamRead, nullptr, BDByteStreamSeek);

  SafeRelease(&m_lavfDemuxer);
  SAFE_CO_FREE(m_StreamClip);
  SAFE_CO_FREE(m_rtOffset);

  m_lavfDemuxer = new CLAVFDemuxer(m_pLock, m_pSettings);
  m_lavfDemuxer->AddRef();
  m_lavfDemuxer->SetBluRay(this);
  if (FAILED(hr = m_lavfDemuxer->OpenInputStream(m_pb, nullptr, "mpegts", TRUE))) {
    SafeRelease(&m_lavfDemuxer);
    return hr;
  }

  if (m_MVCPlayback && !m_lavfDemuxer->m_bH264MVCCombine)
  {
    DbgLog((LOG_TRACE, 10, L"CBDDemuxer::SetTitle(): MVC demuxing was requested, but main demuxer did not activate MVC mode, disabling."));
    CloseMVCExtensionDemuxer();
    m_MVCPlayback = FALSE;
  }

  m_lavfDemuxer->SeekByte(0, 0);

  // Process any events that occured during opening
  ProcessBDEvents();

  // Reset EOS protection
  m_EndOfStreamPacketFlushProtection = FALSE;

  // space for storing stream offsets
  m_StreamClip = (uint16_t *)CoTaskMemAlloc(sizeof(*m_StreamClip) * m_lavfDemuxer->GetNumStreams());
  if (!m_StreamClip)
    return E_OUTOFMEMORY;
  memset(m_StreamClip, -1, sizeof(*m_StreamClip) * m_lavfDemuxer->GetNumStreams());

  m_rtOffset = (REFERENCE_TIME *)CoTaskMemAlloc(sizeof(*m_rtOffset) * m_lavfDemuxer->GetNumStreams());
  if (!m_rtOffset)
    return E_OUTOFMEMORY;
  memset(m_rtOffset, 0, sizeof(*m_rtOffset) * m_lavfDemuxer->GetNumStreams());

  DbgLog((LOG_TRACE, 20, L"Opened BD title with %d clips and %d chapters", m_pTitle->clip_count, m_pTitle->chapter_count));
  return S_OK;
}
Esempio n. 10
0
int
main(int argc, char *argv[])
{
    int title_no = -1;
    int playlist = -1;
    int angle = 0;
    char *bdpath = NULL, *dest = NULL;
    FILE *out;
    int opt;
    int verbose = 0;
    int64_t total = 0;
    int64_t pos, end_pos = -1;
    size_t size, wrote;
    int bytes;
    int title_count;
    BLURAY *bd;
    int chapter_start = 0;
    int chapter_end = -1;
    uint8_t buf[BUF_SIZE];
    char *keyfile = NULL;
    BLURAY_TITLE_INFO *ti;

    do {
        opt = getopt(argc, argv, OPTS);
        switch (opt) {
            case -1:
                if (optind < argc && bdpath == NULL) {
                    bdpath = argv[optind];
                    optind++;
                    opt = 1;
                }
                else if (optind < argc && dest == NULL) {
                    dest = argv[optind];
                    optind++;
                    opt = 1;
                }
                break;

            case 'c': {
                int match;
                match = sscanf(optarg, "%d-%d", &chapter_start, &chapter_end);
                if (match == 1) {
                    chapter_end = chapter_start + 1;
                }
                chapter_start--;
                chapter_end--;
            } break;

            case 'k':
                keyfile = optarg;
                break;

            case 'a':
                angle = atoi(optarg);
                angle--;
                break;

            case 't':
                if (playlist >= 0) {
                    _usage(argv[0]);
                }
                title_no = atoi(optarg);
                title_no--;
                break;

            case 'p':
                if (title_no >= 0) {
                    _usage(argv[0]);
                }
                playlist = atoi(optarg);
                break;

            case 'v':
                verbose = 1;
                break;

            default:
                _usage(argv[0]);
                break;
        }
    } while (opt != -1);

    if (title_no < 0 && playlist < 0) {
        _usage(argv[0]);
    }
    if (optind < argc) {
        _usage(argv[0]);
    }

    bd = bd_open(bdpath, keyfile);
    if (bd == NULL) {
        fprintf(stderr, "Failed to open disc: %s\n", bdpath);
        return 1;
    }

    title_count = bd_get_titles(bd, TITLES_RELEVANT, 0);
    if (title_count <= 0) {
        fprintf(stderr, "No titles found: %s\n", bdpath);
        return 1;
    }

    if (title_no >= 0) {
        if (!bd_select_title(bd, title_no)) {
            fprintf(stderr, "Failed to open title: %d\n", title_no);
            return 1;
        }
        ti = bd_get_title_info(bd, title_no, angle);

    } else {
        if (!bd_select_playlist(bd, playlist)) {
            fprintf(stderr, "Failed to open playlist: %d\n", playlist);
            return 1;
        }
        ti = bd_get_playlist_info(bd, playlist, angle);
    }

    if (dest) {
        out = fopen(dest, "wb");
        if (out == NULL) {
            fprintf(stderr, "Failed to open destination: %s\n", dest);
            return 1;
        }
    } else {
        out = stdout;
    }

    if (angle >= (int)ti->angle_count) {
        fprintf(stderr, "Invalid angle %d > angle count %d. Using angle 1.\n", 
                angle+1, ti->angle_count);
        angle = 0;
    }
    bd_select_angle(bd, angle);

    if (chapter_start >= (int)ti->chapter_count) {
        fprintf(stderr, "First chapter %d > chapter count %d\n", 
                chapter_start+1, ti->chapter_count);
        return 1;
    }
    if (chapter_end >= (int)ti->chapter_count) {
        chapter_end = -1;
    }
    if (chapter_end >= 0) {
        end_pos = bd_chapter_pos(bd, chapter_end);
    }
    bd_free_title_info(ti);

    bd_seek_chapter(bd, chapter_start);
    pos = bd_tell(bd);
    while (end_pos < 0 || pos < end_pos) {
        size = BUF_SIZE;
        if (size > (size_t)(end_pos - pos)) {
            size = end_pos - pos;
        }
        bytes = bd_read(bd, buf, size);
        if (bytes <= 0) {
            break;
        }
        pos = bd_tell(bd);
        wrote = fwrite(buf, 1, bytes, out);
        if (wrote != (size_t)bytes) {
            fprintf(stderr, "read/write sizes do not match: %d/%zu\n", bytes, wrote);
        }
        if (wrote == 0) {
            if (ferror(out)) {
                perror("Write error");
            }
            break;
        }
        total += wrote;
    }
    if (verbose) {
        fprintf(stderr, "Wrote %"PRId64" bytes\n", total);
    }
    bd_close(bd);
    fclose(out);
    return 0;
}
Esempio n. 11
0
static int bluray_stream_open(stream_t *s, int mode,
                              void *opts, int *file_format)
{
    struct stream_priv_s *p = opts;
    struct bluray_priv_s *b;

    BLURAY_TITLE_INFO *info = NULL;
    BLURAY *bd;

    int title, title_guess, title_count;
    uint64_t title_size;

    unsigned int angle = 0;
    uint64_t max_duration = 0;

    char *device = NULL;
    int i;

    /* find the requested device */
    if (p->device)
        device = p->device;
    else if (bluray_device)
        device = bluray_device;

    if (!device) {
        mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_BlurayNoDevice);
        return STREAM_UNSUPPORTED;
    }

    /* open device */
    bd = bd_open(device, NULL);
    if (!bd) {
        mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_CantOpenBluray, device);
        return STREAM_UNSUPPORTED;
    }

    /* check for available titles on disc */
    title_count = bd_get_titles(bd, TITLES_RELEVANT, angle);
    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_BLURAY_TITLES=%d\n", title_count);
    if (!title_count) {
        mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_BlurayNoTitles);
        bd_close(bd);
        return STREAM_UNSUPPORTED;
    }

    /* parse titles information */
    title_guess = BLURAY_DEFAULT_TITLE;
    for (i = 0; i < title_count; i++) {
        BLURAY_TITLE_INFO *ti;
        int sec, msec;

        ti = bd_get_title_info(bd, i, angle);
        if (!ti)
            continue;

        sec  = ti->duration / 90000;
        msec = (ti->duration - sec) % 1000;

        mp_msg(MSGT_IDENTIFY, MSGL_INFO,
               "ID_BLURAY_TITLE_%d_CHAPTERS=%d\n", i + 1, ti->chapter_count);
        mp_msg(MSGT_IDENTIFY, MSGL_INFO,
               "ID_BLURAY_TITLE_%d_ANGLE=%d\n", i + 1, ti->angle_count);
        mp_msg(MSGT_IDENTIFY, MSGL_V,
               "ID_BLURAY_TITLE_%d_LENGTH=%d.%03d\n", i + 1, sec, msec);
        mp_msg(MSGT_IDENTIFY, MSGL_V,
               "ID_BLURAY_TITLE_%d_PLAYLIST=%05d\n", i + 1, ti->playlist);

        /* try to guess which title may contain the main movie */
        if (ti->duration > max_duration) {
            max_duration = ti->duration;
            title_guess = i;
        }

        bd_free_title_info(ti);
    }

    /* Select current title */
    title = p->title ? p->title - 1: title_guess;
    title = FFMIN(title, title_count - 1);

    bd_select_title(bd, title);

    title_size = bd_get_title_size(bd);
    mp_msg(MSGT_IDENTIFY, MSGL_INFO,
           "ID_BLURAY_CURRENT_TITLE=%d\n", title + 1);

    /* Get current title information */
    info = bd_get_title_info(bd, title, angle);
    if (!info)
        goto err_no_info;

    /* Select angle */
    angle = bluray_angle ? bluray_angle : BLURAY_DEFAULT_ANGLE;
    angle = FFMIN(angle, info->angle_count);

    if (angle)
        bd_select_angle(bd, angle);

    mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_BLURAY_CURRENT_ANGLE=%d\n", angle + 1);

    bd_free_title_info(info);

err_no_info:
    s->fill_buffer = bluray_stream_fill_buffer;
    s->seek        = bluray_stream_seek;
    s->close       = bluray_stream_close;
    s->control     = bluray_stream_control;

    b                  = calloc(1, sizeof(struct bluray_priv_s));
    b->bd              = bd;
    b->current_angle   = angle;
    b->current_title   = title;

    s->end_pos     = title_size;
    s->sector_size = BLURAY_SECTOR_SIZE;
    s->flags       = mode | MP_STREAM_SEEK;
    s->priv        = b;
    s->type        = STREAMTYPE_BLURAY;
    s->url         = strdup("br://");

    mp_msg(MSGT_OPEN, MSGL_V, "Blu-ray successfully opened.\n");

    return STREAM_OK;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
int main(int argc, char *argv[])
{
    BLURAY *bd;
    int count, ii, opt;
    unsigned int seconds = 0;
    unsigned int flags = TITLES_RELEVANT;
    char *bd_dir = NULL;

    BD_DEBUG(DBG_BLURAY,"\nListing titles:\n");

    do
    {
        opt = getopt(argc, argv, OPTS);
        switch (opt)
        {
            case -1:
                if (optind < argc && bd_dir == NULL)
                {
                    bd_dir = argv[optind];
                    optind++;
                    opt = 1;
                }
                break;
            case 'a':
                flags = TITLES_ALL;
                break;
            case 's':
                seconds = strtol(optarg, NULL, 0);
                break;
            case 'h':
            default:
                _usage(argv[0]);
                break;
        }
    } while (opt != -1);

    if (bd_dir == NULL)
    {
        _usage(argv[0]);
    }
    bd = bd_open(bd_dir, NULL);

    count = bd_get_titles(bd, flags, seconds);
    for (ii = 0; ii < count; ii++)
    {
        BLURAY_TITLE_INFO* ti;
        ti = bd_get_title_info(bd, ii, 0);
        printf(
       "index: %d duration: %02"PRIu64":%02"PRIu64":%02"PRIu64" chapters: %3d angles: %2u clips: %3u (playlist: %05d.mpls) "
       "V:%d A:%-2d PG:%-2d IG:%-2d SV:%d SA:%d\n",
              ii + 1,
              (ti->duration / 90000) / (3600),
              ((ti->duration / 90000) % 3600) / 60,
              ((ti->duration / 90000) % 60),
              ti->chapter_count, ti->angle_count, ti->clip_count, ti->playlist,
              ti->clips[0].video_stream_count,
              ti->clips[0].audio_stream_count,
              ti->clips[0].pg_stream_count,
              ti->clips[0].ig_stream_count,
              ti->clips[0].sec_video_stream_count,
              ti->clips[0].sec_audio_stream_count
        );
        bd_free_title_info(ti);
    }
    bd_close(bd);
    return 0;
}
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_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;
        BLURAY_TITLE_INFO *ti = bd_get_title_info(b->bd, b->current_title, b->current_angle);
        if (ti->clip_count) {
            BLURAY_STREAM_INFO *si = NULL;
            int count = 0;
            switch (req->type) {
            case stream_ctrl_audio:
                count = ti->clips[0].audio_stream_count;
                si = ti->clips[0].audio_streams;
                break;
            case stream_ctrl_sub:
                count = ti->clips[0].pg_stream_count;
                si = ti->clips[0].pg_streams;
                break;
            }
            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++;
            }
        }
        bd_free_title_info(ti);
        return STREAM_ERROR;
    }

    default:
        break;
    }

    return STREAM_UNSUPPORTED;
}
Esempio n. 15
0
bool BDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
{
    VERBOSE(VB_IMPORTANT, LOC + QString("Opened BDRingBuffer device at %1")
            .arg(lfilename.toLatin1().data()));

    rwlock.lockForWrite();

    if (bdnav)
    {
        if (m_currentTitleInfo)
            bd_free_title_info(m_currentTitleInfo);
        bd_close(bdnav);
        bdnav = NULL;
    }

    filename = lfilename;

    QString keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir());
    QByteArray keyarray = keyfile.toAscii();
    const char *keyfilepath = keyarray.data();

    bdnav = bd_open(lfilename.toLatin1().data(), keyfilepath);

    if (!bdnav)
    {
        rwlock.unlock();
        return false;
    }

    // Check disc to see encryption status, menu and navigation types.
    const BLURAY_DISC_INFO *discinfo = bd_get_disc_info(bdnav);
    if (discinfo)
    {
        VERBOSE(VB_PLAYBACK, QString(
                    "*** Blu-ray Disc Information ***\n"
                    "First Play Supported: %1\n"
                    "Top Menu Supported: %2\n"
                    "Number of HDMV Titles: %3\n"
                    "Number of BD-J Titles: %4\n"
                    "Number of Unsupported Titles: %5\n"
                    "AACS present on disc: %6\n"
                    "libaacs used: %7\n"
                    "AACS handled: %8\n"
                    "BD+ present on disc: %9\n"
                    "libbdplus used: %10\n"
                    "BD+ handled: %11")
                .arg(discinfo->first_play_supported ? "yes" : "no")
                .arg(discinfo->top_menu_supported ? "yes" : "no")
                .arg(discinfo->num_hdmv_titles)
                .arg(discinfo->num_bdj_titles)
                .arg(discinfo->num_unsupported_titles)
                .arg(discinfo->aacs_detected ? "yes" : "no")
                .arg(discinfo->libaacs_detected ? "yes" : "no")
                .arg(discinfo->aacs_handled ? "yes" : "no")
                .arg(discinfo->bdplus_detected ? "yes" : "no")
                .arg(discinfo->libbdplus_detected ? "yes" : "no")
                .arg(discinfo->bdplus_handled ? "yes" : "no"));
    }

    // The following settings affect HDMV navigation
    // (default audio track selection,
    // parental controls, menu language, etc.  They are not yet used.

    // Set parental level "age" to 99 for now.  TODO: Add support for FE level
    bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_PARENTAL, 99);

    // Set preferred language to FE guide language
    const char *langpref = gCoreContext->GetSetting(
        "ISO639Language0", "eng").toLatin1().data();
    QString QScountry  = gCoreContext->GetLocale()->GetCountryCode().toLower();
    const char *country = QScountry.toLatin1().data();
    bd_set_player_setting_str(
        bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);

    // Set preferred presentation graphics language to the FE guide language
    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_PG_LANG, langpref);

    // Set preferred menu language to the FE guide language
    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref);

    // Set player country code via MythLocale. (not a region setting)
    bd_set_player_setting_str(
        bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country);

    int regioncode = 0;
    regioncode = gCoreContext->GetNumSetting("BlurayRegionCode");
    if (regioncode > 0)
        bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_REGION_CODE, regioncode);

    VERBOSE(VB_IMPORTANT, LOC + QString("Using %1 as keyfile...")
            .arg(QString(keyfilepath)));

    // Return an index of relevant titles (excludes dupe clips + titles)
    m_numTitles = bd_get_titles(bdnav, TITLES_RELEVANT);
    m_mainTitle = 0;
    m_currentTitleLength = 0;
    m_titlesize = 0;
    m_currentTime = 0;
    m_currentTitleInfo = NULL;
    m_currentTitleAngleCount = 0;

    // Mostly event-driven values below
    m_currentAngle = 0;
    m_currentTitle = 0;
    m_currentPlaylist = 0;
    m_currentPlayitem = 0;
    m_currentChapter = 0;
    m_currentAudioStream = 0;
    m_currentIGStream = 0;
    m_currentPGTextSTStream = 0;
    m_currentSecondaryAudioStream = 0;
    m_currentSecondaryVideoStream = 0;
    m_PGTextSTEnabled = false;
    m_secondaryAudioEnabled = false;
    m_secondaryVideoEnabled = false;
    m_secondaryVideoIsFullscreen = false;
    m_still = 0;
    m_inMenu = false;

    VERBOSE(VB_IMPORTANT, LOC + QString("Found %1 relevant titles.")
            .arg(m_numTitles));

    // Loop through the relevant titles and find the longest
    uint64_t titleLength = 0;
    uint64_t margin      = 90000 << 4; // approx 30s
    BLURAY_TITLE_INFO *titleInfo = NULL;
    for( unsigned i = 0; i < m_numTitles; ++i)
    {
        titleInfo = bd_get_title_info(bdnav, i);
        if (titleLength == 0 ||
            (titleInfo->duration > (titleLength + margin)))
        {
            m_mainTitle = titleInfo->idx;
            titleLength = titleInfo->duration;
        }
    }

    bd_free_title_info(titleInfo);

    SwitchTitle(m_mainTitle);

#if 0
    // First, attempt to initialize the disc in HDMV navigation mode.
    // If this fails, fall back to the traditional built-in title switching
    // mode.
    if (bd_play(bdnav))
    {
        m_is_hdmv_navigation = true;

        // Initialize the HDMV event queue
        HandleBDEvents();

        // Register the Menu Overlay Callback
        bd_register_overlay_proc(bdnav, this, HandleOverlayCallback);
    }
#endif

    readblocksize   = BD_BLOCK_SIZE * 62;
    setswitchtonext = false;
    ateof           = false;
    commserror      = false;
    numfailures     = 0;
    rawbitrate      = 8000;
    CalcReadAheadThresh();

    rwlock.unlock();

    return true;
}
Esempio n. 16
0
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_CHAPTER: {
        *((unsigned int *) arg) = b->current_chapter;
        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_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;
    }

    default:
        break;
    }

    return STREAM_UNSUPPORTED;
}