Пример #1
0
static int enable_cache(struct MPContext *mpctx, struct stream **stream,
                        struct demuxer **demuxer, struct demuxer_params *params)
{
    struct MPOpts *opts = mpctx->opts;

    if (opts->stream_cache_size <= 0)
        return 0;

    char *filename = talloc_strdup(NULL, (*demuxer)->filename);
    free_demuxer(*demuxer);
    free_stream(*stream);

    *stream = stream_open(filename, opts);
    if (!*stream) {
        talloc_free(filename);
        return -1;
    }

    stream_enable_cache_percent(stream,
                                opts->stream_cache_size,
                                opts->stream_cache_def_size,
                                opts->stream_cache_min_percent,
                                opts->stream_cache_seek_min_percent);

    *demuxer = demux_open(*stream, "mkv", params, opts);
    if (!*demuxer) {
        talloc_free(filename);
        free_stream(*stream);
        return -1;
    }

    talloc_free(filename);
    return 1;
}
Пример #2
0
static void demux_close_demuxers(demuxer_t* demuxer) {
  dd_priv_t* priv = demuxer->priv;
  stream_t *s;

  if(priv->vd)
    free_demuxer(priv->vd);
  if(priv->ad && priv->ad != priv->vd) {
    // That's a hack to free the audio file stream
    // It's ok atm but we shouldn't free that here
    s = priv->ad->stream;
    free_demuxer(priv->ad);
    free_stream(s);
  } if(priv->sd && priv->sd != priv->vd && priv->sd != priv->ad) {
    s = priv->sd->stream;
    free_demuxer(priv->sd);
    free_stream(s);
  }

  free(priv);
}
Пример #3
0
// segment = get Nth segment of a multi-segment file
static bool check_file_seg(struct MPContext *mpctx, struct demuxer **sources,
                           int num_sources, unsigned char uid_map[][16],
                           char *filename, int segment)
{
    bool was_valid = false;
    struct demuxer_params params = {
        .matroska_wanted_uids = uid_map,
        .matroska_wanted_segment = segment,
        .matroska_was_valid = &was_valid,
    };
    struct stream *s = stream_open(filename, mpctx->opts);
    if (!s)
        return false;
    struct demuxer *d = demux_open(s, "mkv", &params, mpctx->opts);

    if (!d) {
        free_stream(s);
        return was_valid;
    }
    if (d->type == DEMUXER_TYPE_MATROSKA) {
        for (int i = 1; i < num_sources; i++) {
            if (sources[i])
                continue;
            if (!memcmp(uid_map[i], d->matroska_data.segment_uid, 16)) {
                mp_msg(MSGT_CPLAYER, MSGL_INFO, "Match for source %d: %s\n",
                       i, d->filename);

                if (enable_cache(mpctx, &s, &d, &params) < 0)
                    continue;

                sources[i] = d;
                return true;
            }
        }
    }
    free_demuxer(d);
    free_stream(s);
    return was_valid;
}
Пример #4
0
static struct demuxer *open_given_type(struct MPOpts *opts,
                                       const struct demuxer_desc *desc,
                                       struct stream *stream, bool force,
                                       int audio_id, int video_id, int sub_id,
                                       char *filename,
                                       struct demuxer_params *params)
{
    struct demuxer *demuxer;
    int fformat;
    demuxer = new_demuxer(opts, stream, desc->type, audio_id,
                          video_id, sub_id, filename);
    demuxer->params = params;
    if (desc->check_file)
        fformat = desc->check_file(demuxer);
    else
        fformat = desc->type;
    if (force)
        fformat = desc->type;
    if (fformat == 0)
        goto fail;
    if (fformat == desc->type) {
        if (demuxer->filetype)
            mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s (%s)\n",
                    demuxer->filetype, desc->shortdesc);
        else
            mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s\n",
                    desc->shortdesc);
        if (demuxer->desc->open) {
            struct demuxer *demux2 = demuxer->desc->open(demuxer);
            if (!demux2) {
                mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Opening as detected format "
                        "\"%s\" failed.\n", desc->shortdesc);
                goto fail;
            }
            /* At least demux_mov can return a demux_demuxers instance
             * from open() instead of the original fed in. */
            demuxer = demux2;
        }
        demuxer->file_format = fformat;
        return demuxer;
    } else {
        // demux_mov can return playlist instead of mov
        if (fformat == DEMUXER_TYPE_PLAYLIST)
            return demuxer; // handled in mplayer.c
        /* Internal MPEG PS demuxer check can return other MPEG subtypes
         * which don't have their own checks; recurse to try opening as
         * the returned type instead. */
        free_demuxer(demuxer);
        desc = get_demuxer_desc_from_type(fformat);
        if (!desc) {
            mp_msg(MSGT_DEMUXER, MSGL_ERR,
                   "BUG: recursion to nonexistent file format\n");
            return NULL;
        }
        return open_given_type(opts, desc, stream, false, audio_id,
                               video_id, sub_id, filename, params);
    }
 fail:
    free_demuxer(demuxer);
    return NULL;
}
Пример #5
0
static int d_open(demuxer_t *demuxer, enum demux_check check)
{
    struct priv *p = demuxer->priv = talloc_zero(demuxer, struct priv);

    if (check != DEMUX_CHECK_FORCE)
        return -1;

    struct demuxer_params params = {.force_format = "+lavf"};

    if (demuxer->stream->uncached_type == STREAMTYPE_CDDA)
        params.force_format = "+rawaudio";

    char *t = NULL;
    stream_control(demuxer->stream, STREAM_CTRL_GET_DISC_NAME, &t);
    if (t) {
        mp_tags_set_str(demuxer->metadata, "TITLE", t);
        talloc_free(t);
    }

    // Initialize the playback time. We need to read _some_ data to get the
    // correct stream-layer time (at least with libdvdnav).
    stream_peek(demuxer->stream, 1);
    reset_pts(demuxer);

    p->slave = demux_open(demuxer->stream, &params, demuxer->global);
    if (!p->slave)
        return -1;

    // So that we don't miss initial packets of delayed subtitle streams.
    demux_set_stream_autoselect(p->slave, true);

    // With cache enabled, the stream can be seekable. This causes demux_lavf.c
    // (actually libavformat/mpegts.c) to seek sometimes when reading a packet.
    // It does this to seek back a bit in case the current file position points
    // into the middle of a packet.
    if (demuxer->stream->uncached_type != STREAMTYPE_CDDA) {
        demuxer->stream->seekable = false;

        // Can be seekable even if the stream isn't.
        demuxer->seekable = true;

        demuxer->rel_seeks = true;
    }

    add_dvd_streams(demuxer);
    add_streams(demuxer);
    add_stream_chapters(demuxer);

    return 0;
}

static void d_close(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;
    free_demuxer(p->slave);
}

static int d_control(demuxer_t *demuxer, int cmd, void *arg)
{
    struct priv *p = demuxer->priv;

    switch (cmd) {
    case DEMUXER_CTRL_GET_TIME_LENGTH: {
        double len;
        if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &len) < 1)
            break;
        *(double *)arg = len;
        return DEMUXER_CTRL_OK;
    }
    case DEMUXER_CTRL_RESYNC:
        demux_flush(p->slave);
        break; // relay to slave demuxer
    case DEMUXER_CTRL_SWITCHED_TRACKS:
        reselect_streams(demuxer);
        return DEMUXER_CTRL_OK;
    }
    return demux_control(p->slave, cmd, arg);
}

const demuxer_desc_t demuxer_desc_disc = {
    .name = "disc",
    .desc = "CD/DVD/BD wrapper",
    .fill_buffer = d_fill_buffer,
    .open = d_open,
    .close = d_close,
    .seek = d_seek,
    .control = d_control,
};
Пример #6
0
static void d_close(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;
    free_demuxer(p->slave);
}