Пример #1
0
int64_t CBDDemuxer::BDByteStreamSeek(void *opaque,  int64_t offset, int whence)
{
  CBDDemuxer *demux = (CBDDemuxer *)opaque;
  BLURAY *bd = demux->m_pBD;

  int64_t pos = 0;
  if (whence == SEEK_SET) {
    pos = offset;
  } else if (whence == SEEK_CUR) {
    if (offset == 0)
      return bd_tell(bd);
    pos = bd_tell(bd) + offset;
  } else if (whence == SEEK_END) {
    pos = bd_get_title_size(bd) - offset;
  } else if (whence == AVSEEK_SIZE) {
    return bd_get_title_size(bd);
  } else
    return -1;
  if (pos < 0)
    pos = 0;
  int64_t achieved = bd_seek(bd, pos);
  if (pos > achieved) {
    offset = pos - achieved;
    DbgLog((LOG_TRACE, 10, L"BD Seek to %I64d, achieved %I64d, correcting target by %I64d", pos, achieved, offset));
    uint8_t *dump_buffer = (uint8_t *)CoTaskMemAlloc(6144);
    while (offset > 0) {
      bd_read(bd, dump_buffer, min(offset, 6144));
      offset -= 6144;
    }
    CoTaskMemFree(dump_buffer);
    achieved = bd_tell(bd);
  }
  return achieved;
}
Пример #2
0
static uint64_t align_to_next_packet(BLURAY *bd, uint8_t *pkt)
{
    uint8_t buf[MAX_HOLE];
    uint64_t pos = 0;
    uint64_t start = bd_tell(bd);
    uint64_t orig;
    uint64_t off = 192;

    memcpy(buf, pkt, 192);
    if ( start >= 192 ) {
        start -= 192;
    }
    orig = start;

    while (1)
    {
        if (bd_read(bd, buf+off, sizeof(buf)-off) == sizeof(buf)-off)
        {
            const uint8_t *bp = buf;
            int i;

            for ( i = sizeof(buf) - 8 * 192; --i >= 0; ++bp )
            {
                if ( have_ts_sync( bp, 192 ) )
                {
                    break;
                }
            }
            if ( i >= 0 )
            {
                pos = ( bp - buf );
                break;
            }
            off = 8 * 192;
            memcpy(buf, buf + sizeof(buf) - off, off);
            start += sizeof(buf) - off;
        }
        else
        {
            return 0;
        }
    }
    off = start + pos - 4;
    // bd_seek seeks to the nearest access unit *before* the requested position
    // we don't want to seek backwards, so we need to read until we get
    // past that position.
    bd_seek(bd, off);
    while (off > bd_tell(bd))
    {
        if (bd_read(bd, buf, 192) != 192)
        {
            break;
        }
    }
    return start - orig + pos;
}
Пример #3
0
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(bdnav);
    return result;
}
Пример #4
0
STDMETHODIMP CBDDemuxer::Seek(REFERENCE_TIME rTime)
{
  int64_t prev = bd_tell(m_pBD);

  int64_t target = bd_find_seek_point(m_pBD, ConvertDSTimeTo90Khz(rTime));
  m_EndOfStreamPacketFlushProtection = FALSE;

  DbgLog((LOG_TRACE, 1, "Seek Request: %I64u (time); %I64u (byte), %I64u (prev byte)", rTime, target, prev));
  HRESULT hr = m_lavfDemuxer->SeekByte(target + 4, AVSEEK_FLAG_BACKWARD);

  if (m_MVCPlayback && m_MVCFormatContext) {
    // Re-open to switch clip if needed
    CloseMVCExtensionDemuxer();
    if (FAILED(OpenMVCExtensionDemuxer(m_NewClip)))
      return E_FAIL;

    // Adjust for clip offset
    int64_t seek_pts = 0;
    if (rTime > 0) {
      AVStream *stream = m_MVCFormatContext->streams[m_MVCStreamIndex];

      rTime -= m_rtNewOffset;
      rTime -= 10000000; // seek one second before the target to ensure the MVC queue isn't out of sync for too long
      seek_pts = m_lavfDemuxer->ConvertRTToTimestamp(rTime, stream->time_base.num, stream->time_base.den);
    }

    if (seek_pts < 0)
      seek_pts = 0;

    av_seek_frame(m_MVCFormatContext, m_MVCStreamIndex, seek_pts, AVSEEK_FLAG_BACKWARD);
  }
  return hr;
}
Пример #5
0
static int next_packet( BLURAY *bd, uint8_t *pkt )
{
    int result;

    while ( 1 )
    {
        result = bd_read( bd, pkt, 192 );
        if ( result < 0 )
        {
            return -1;
        }
        if ( result < 192 )
        {
            return 0;
        }
        // Sync byte is byte 4.  0-3 are timestamp.
        if (pkt[4] == 0x47)
        {
            return 1;
        }
        // lost sync - back up to where we started then try to re-establish.
        uint64_t pos = bd_tell(bd);
        uint64_t pos2 = align_to_next_packet(bd, pkt);
        if ( pos2 == 0 )
        {
            hb_log( "next_packet: eof while re-establishing sync @ %"PRId64, pos );
            return 0;
        }
        hb_log( "next_packet: sync lost @ %"PRId64", regained after %"PRId64" bytes",
                 pos, pos2 );
    }
}
Пример #6
0
__int64 CDVDInputStreamBluray::Seek(__int64 offset, int whence)
{
#if LIBBLURAY_BYTESEEK
  if(whence == SEEK_POSSIBLE)
    return 1;
  else if(whence == SEEK_CUR)
  {
    if(offset == 0)
      return m_dll->bd_tell(m_bd);
    else
      offset += bd_tell(m_bd);
  }
  else if(whence == SEEK_END)
    offset += m_dll->bd_get_title_size(m_bd);
  else if(whence != SEEK_SET)
    return -1;

  int64_t pos = m_dll->bd_seek(m_bd, offset);
  if(pos < 0)
  {
    CLog::Log(LOGERROR, "CDVDInputStreamBluray::Seek - seek to %"PRId64", failed with %"PRId64, offset, pos);
    return -1;
  }

  if(pos != offset)
    CLog::Log(LOGWARNING, "CDVDInputStreamBluray::Seek - seek to %"PRId64", ended at %"PRId64, offset, pos);

  return offset;
#else
  if(whence == SEEK_POSSIBLE)
    return 0;
  return -1;
#endif
}
Пример #7
0
STDMETHODIMP CBDDemuxer::Seek(REFERENCE_TIME rTime)
{
  int64_t prev = bd_tell(m_pBD);

  int64_t target = bd_find_seek_point(m_pBD, ConvertDSTimeTo90Khz(rTime));

  DbgLog((LOG_TRACE, 1, "Seek Request: %I64u (time); %I64u (byte), %I64u (prev byte)", rTime, target, prev));
  return m_lavfDemuxer->SeekByte(target, AVSEEK_FLAG_BACKWARD);
}
Пример #8
0
int64_t BDByteStreamSeek(void *opaque,  int64_t offset, int whence)
{
  BLURAY *bd = (BLURAY *)opaque;

  int64_t pos = 0;
  if (whence == SEEK_SET) {
    pos = offset;
  } else if (whence == SEEK_CUR) {
    if (offset == 0)
      return bd_tell(bd);
    pos = bd_tell(bd) + offset;
  } else if (whence == SEEK_END) {
    pos = bd_get_title_size(bd) - offset;
  } else if (whence == AVSEEK_SIZE) {
    return bd_get_title_size(bd);
  } else
    return -1;
  return bd_seek(bd, pos);
}
Пример #9
0
static int bluray_stream_seek(stream_t *s, int64_t pos)
{
    struct bluray_priv_s *b = s->priv;
    int64_t p;

    p = bd_seek(b->bd, pos);
    // bd_seek does not say what happens on errors,
    // so be extra paranoid.
    // bd_seek also does not seek exactly to the requested
    // position, so allow for some fuzz.
    if (p < 0 || p > pos || p + 20*1024*1024 < pos) {
        s->pos = bd_tell(b->bd);
        return 0;
    }

    s->pos = p;
    return 1;
}
Пример #10
0
long long BDRingBuffer::GetReadPosition(void) const
{
    if (bdnav)
        return bd_tell(bdnav);
    return 0;
}
Пример #11
0
/***********************************************************************
 * hb_bd_read
 ***********************************************************************
 *
 **********************************************************************/
hb_buffer_t * hb_bd_read( hb_bd_t * d )
{
    int result;
    int error_count = 0;
    uint8_t buf[192];
    BD_EVENT event;
    uint64_t pos;
    hb_buffer_t * out = NULL;
    uint8_t discontinuity;

    while ( 1 )
    {
        discontinuity = 0;
        result = next_packet( d->bd, buf );
        if ( result < 0 )
        {
            hb_error("bd: Read Error");
            pos = bd_tell( d->bd );
            bd_seek( d->bd, pos + 192 );
            error_count++;
            if (error_count > 10)
            {
                hb_error("bd: Error, too many consecutive read errors");
                hb_set_work_error(d->h, HB_ERROR_READ);
                return NULL;
            }
            continue;
        }
        else if ( result == 0 )
        {
            return NULL;
        }

        error_count = 0;
        while ( bd_get_event( d->bd, &event ) )
        {
            switch ( event.event )
            {
                case BD_EVENT_CHAPTER:
                    // The muxers expect to only get chapter 2 and above
                    // They write chapter 1 when chapter 2 is detected.
                    if (event.param > d->chapter)
                    {
                        d->next_chap = event.param;
                    }
                    break;

                case BD_EVENT_PLAYITEM:
                    discontinuity = 1;
                    hb_deep_log(2, "bd: Playitem %u", event.param);
                    break;

                case BD_EVENT_STILL:
                    bd_read_skip_still( d->bd );
                    break;

                default:
                    break;
            }
        }
        // buf+4 to skip the BD timestamp at start of packet
        if (d->chapter != d->next_chap)
        {
            d->chapter = d->next_chap;
            out = hb_ts_decode_pkt(d->stream, buf+4, d->chapter, discontinuity);
        }
        else
        {
            out = hb_ts_decode_pkt(d->stream, buf+4, 0, discontinuity);
        }
        if (out != NULL)
        {
            return out;
        }
    }
    return NULL;
}
Пример #12
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;
}
Пример #13
0
/***********************************************************************
 * hb_bd_read
 ***********************************************************************
 *
 **********************************************************************/
hb_buffer_t * hb_bd_read( hb_bd_t * d )
{
    int result;
    int error_count = 0;
    uint8_t buf[192];
    BD_EVENT event;
    uint64_t pos;
    hb_buffer_t * b;
    uint8_t discontinuity;
    int new_chap = 0;

    discontinuity = 0;
    while ( 1 )
    {
        if ( d->next_chap != d->chapter )
        {
            new_chap = d->chapter = d->next_chap;
        }
        result = next_packet( d->bd, buf );
        if ( result < 0 )
        {
            hb_error("bd: Read Error");
            pos = bd_tell( d->bd );
            bd_seek( d->bd, pos + 192 );
            error_count++;
            if (error_count > 10)
            {
                hb_error("bd: Error, too many consecutive read errors");
                return 0;
            }
            continue;
        }
        else if ( result == 0 )
        {
            return 0;
        }

        error_count = 0;
        while ( bd_get_event( d->bd, &event ) )
        {
            switch ( event.event )
            {
                case BD_EVENT_CHAPTER:
                    // The muxers expect to only get chapter 2 and above
                    // They write chapter 1 when chapter 2 is detected.
                    d->next_chap = event.param;
                    break;

                case BD_EVENT_PLAYITEM:
                    discontinuity = 1;
                    hb_deep_log(2, "bd: Playitem %u", event.param);
                    break;

                case BD_EVENT_STILL:
                    bd_read_skip_still( d->bd );
                    break;

                default:
                    break;
            }
        }
        // buf+4 to skip the BD timestamp at start of packet
        b = hb_ts_decode_pkt( d->stream, buf+4 );
        if ( b )
        {
            b->s.discontinuity = discontinuity;
            b->s.new_chap = new_chap;
            return b;
        }
    }
    return NULL;
}
Пример #14
0
JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_tell(bdj->bd);
}