コード例 #1
0
ファイル: parse_configfile.c プロジェクト: jmglogow/mpv
static bstr read_file(struct mp_log *log, const char *filename)
{
    FILE *f = fopen(filename, "rb");
    if (!f) {
        mp_verbose(log, "Can't open config file: %s\n", mp_strerror(errno));
        return (bstr){0};
    }
    char *data = talloc_array(NULL, char, 0);
    size_t size = 0;
    while (1) {
        size_t left = talloc_get_size(data) - size;
        if (!left) {
            MP_TARRAY_GROW(NULL, data, size + 1);
            continue;
        }
        size_t s = fread(data + size, 1, left, f);
        if (!s) {
            if (ferror(f))
                mp_err(log, "Error reading config file.\n");
            fclose(f);
            MP_TARRAY_APPEND(NULL, data, size, 0);
            return (bstr){data, size - 1};
        }
        size += s;
    }
    assert(0);
}
コード例 #2
0
ファイル: ebml.c プロジェクト: cfxks1989/mpv
/*
 * Skip to (probable) next cluster (MATROSKA_ID_CLUSTER) element start position.
 */
int ebml_resync_cluster(struct mp_log *log, stream_t *s)
{
    int64_t pos = stream_tell(s);
    uint32_t last_4_bytes = 0;
    mp_err(log, "Corrupt file detected. "
           "Trying to resync starting from position %"PRId64"...\n", pos);
    while (!s->eof) {
        // Assumes MATROSKA_ID_CLUSTER is 4 bytes, with no 0 bytes.
        if (last_4_bytes == MATROSKA_ID_CLUSTER) {
            mp_err(log, "Cluster found at %"PRId64".\n", pos - 4);
            stream_seek(s, pos - 4);
            return 0;
        }
        last_4_bytes = (last_4_bytes << 8) | stream_read_char(s);
        pos++;
    }
    return -1;
}
コード例 #3
0
ファイル: av_common.c プロジェクト: rcombs/mpv
// kv is in the format as by OPT_KEYVALUELIST(): kv[0]=key0, kv[1]=val0, ...
// Set these options on given avobj (using av_opt_set..., meaning avobj must
// point to a struct that has AVClass as first member).
// Options which fail to set (error or not found) are printed to log.
// Returns: >=0 success, <0 failed to set an option
int mp_set_avopts(struct mp_log *log, void *avobj, char **kv)
{
    int success = 0;
    for (int n = 0; kv && kv[n * 2]; n++) {
        char *k = kv[n * 2 + 0];
        char *v = kv[n * 2 + 1];
        resolve_positional_arg(avobj, &k);
        int r = av_opt_set(avobj, k, v, AV_OPT_SEARCH_CHILDREN);
        if (r == AVERROR_OPTION_NOT_FOUND) {
            mp_err(log, "AVOption '%s' not found.\n", k);
            success = -1;
        } else if (r < 0) {
            char errstr[80];
            av_strerror(r, errstr, sizeof(errstr));
            mp_err(log, "Could not set AVOption %s='%s' (%s)\n", k, v, errstr);
            success = -1;
        }
    }
    return success;
}
コード例 #4
0
ファイル: tv.c プロジェクト: candux/mpv
static tvi_handle_t *tv_begin(tv_param_t* tv_param, struct mp_log *log)
{
    int i;
    tvi_handle_t* h;
    if(tv_param->driver && !strcmp(tv_param->driver,"help")){
        mp_info(log, "Available drivers:\n");
        for(i=0;tvi_driver_list[i];i++){
            mp_info(log, " %s\t%s",tvi_driver_list[i]->short_name,tvi_driver_list[i]->name);
            if(tvi_driver_list[i]->comment)
                mp_info(log, " (%s)",tvi_driver_list[i]->comment);
            mp_info(log, "\n");
        }
        return NULL;
    }

    for(i=0;tvi_driver_list[i];i++){
        if (!tv_param->driver || !strcmp(tvi_driver_list[i]->short_name, tv_param->driver)){
            h=tvi_driver_list[i]->tvi_init(log, tv_param);
            //Requested driver initialization failed
            if (!h && tv_param->driver)
                return NULL;
            //Driver initialization failed during autodetection process.
            if (!h)
                continue;

            h->tv_param=tv_param;
            MP_INFO(h, "Selected driver: %s\n name: %s\n author: %s\n comment: %s\n", tvi_driver_list[i]->short_name,
            tvi_driver_list[i]->name,
            tvi_driver_list[i]->author,
            tvi_driver_list[i]->comment?tvi_driver_list[i]->comment:"");
            tv_param->driver=strdup(tvi_driver_list[i]->short_name);
            return h;
        }
    }

    if(tv_param->driver)
        mp_err(log, "No such driver: %s\n", tv_param->driver);
    else
        mp_err(log, "TV driver autodetection failed.\n");
    return NULL;
}
コード例 #5
0
ファイル: charset_conv.c プロジェクト: 0x0all/mpv
static const char *libguess_guess(struct mp_log *log, bstr buf,
                                  const char *language)
{
    if (!language || !language[0] || strcmp(language, "help") == 0) {
        mp_err(log, "libguess needs a language: "
               "japanese taiwanese chinese korean russian arabic turkish "
               "greek hebrew polish baltic\n");
        return NULL;
    }

    return libguess_determine_encoding(buf.start, buf.len, language);
}
コード例 #6
0
ファイル: dvb_tune.c プロジェクト: Deadsign/mpv
int dvb_get_tuner_type(int fe_fd, struct mp_log *log)
{
  struct dvb_frontend_info fe_info;

  int res;

  res = ioctl(fe_fd, FE_GET_INFO, &fe_info);
  if(res < 0)
  {
        mp_err(log, "FE_GET_INFO error: %d, FD: %d\n\n", errno, fe_fd);
        return 0;
  }

  switch(fe_info.type)
  {
        case FE_OFDM:
      mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-T\n");
          return TUNER_TER;

        case FE_QPSK:
      mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-S\n");
          return TUNER_SAT;

        case FE_QAM:
      mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-C\n");
          return TUNER_CBL;

#ifdef DVB_ATSC
        case FE_ATSC:
      mp_verbose(log, "TUNER TYPE SEEMS TO BE DVB-ATSC\n");
          return TUNER_ATSC;
#endif
        default:
          mp_err(log, "UNKNOWN TUNER TYPE\n");
          return 0;
  }

}
コード例 #7
0
ファイル: playlist.c プロジェクト: 0x0all/mpv
struct playlist *playlist_parse_file(const char *file, struct mpv_global *global)
{
    struct mp_log *log = mp_log_new(NULL, global->log, "!playlist_parser");
    mp_verbose(log, "Parsing playlist file %s...\n", file);

    struct playlist *ret = NULL;
    stream_t *stream = stream_open(file, global);
    if(!stream) {
        mp_err(log, "Error while opening playlist file %s\n", file);
        talloc_free(log);
        return NULL;
    }

    struct demuxer *pl_demux = demux_open(stream, "playlist", NULL, global);
    if (pl_demux && pl_demux->playlist) {
        ret = talloc_zero(NULL, struct playlist);
        playlist_transfer_entries(ret, pl_demux->playlist);
    }
コード例 #8
0
ファイル: ebml.c プロジェクト: AppleNuts/mpv
/*
 * Skip the current element.
 * end: the end of the parent element or -1 (for robust error handling)
 */
int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s)
{
    uint64_t len;

    int64_t pos = stream_tell(s);

    len = ebml_read_length(s);
    if (len == EBML_UINT_INVALID)
        goto invalid;

    int64_t pos2 = stream_tell(s);
    if (len >= INT64_MAX - pos2 || (end > 0 && pos2 + len > end))
        goto invalid;

    if (!stream_skip(s, len))
        goto invalid;

    return 0;

invalid:
    mp_err(log, "Invalid EBML length at position %"PRId64"\n", pos);
    stream_seek(s, pos);
    return 1;
}
コード例 #9
0
ファイル: charset_conv.c プロジェクト: 0x0all/mpv
// Use iconv to convert buf to UTF-8.
// Returns buf.start==NULL on error. Returns buf if cp is NULL, or if there is
// obviously no conversion required (e.g. if cp is "UTF-8").
// Returns a newly allocated buffer if conversion is done and succeeds. The
// buffer will be terminated with 0 for convenience (the terminating 0 is not
// included in the returned length).
// Free the returned buffer with talloc_free().
//  buf: input data
//  cp: iconv codepage (or NULL)
//  flags: combination of MP_ICONV_* flags
//  returns: buf (no conversion), .start==NULL (error), or allocated buffer
bstr mp_iconv_to_utf8(struct mp_log *log, bstr buf, const char *cp, int flags)
{
#if HAVE_ICONV
    if (!cp || !cp[0] || mp_charset_is_utf8(cp))
        return buf;

    if (strcasecmp(cp, "ASCII") == 0)
        return buf;

    if (strcasecmp(cp, "UTF-8-BROKEN") == 0)
        return bstr_sanitize_utf8_latin1(NULL, buf);

    iconv_t icdsc;
    if ((icdsc = iconv_open("UTF-8", cp)) == (iconv_t) (-1)) {
        if (flags & MP_ICONV_VERBOSE)
            mp_err(log, "Error opening iconv with codepage '%s'\n", cp);
        goto failure;
    }

    size_t size = buf.len;
    size_t osize = size;
    size_t ileft = size;
    size_t oleft = size - 1;

    char *outbuf = talloc_size(NULL, osize);
    char *ip = buf.start;
    char *op = outbuf;

    while (1) {
        int clear = 0;
        size_t rc;
        if (ileft)
            rc = iconv(icdsc, &ip, &ileft, &op, &oleft);
        else {
            clear = 1; // clear the conversion state and leave
            rc = iconv(icdsc, NULL, NULL, &op, &oleft);
        }
        if (rc == (size_t) (-1)) {
            if (errno == E2BIG) {
                size_t offset = op - outbuf;
                outbuf = talloc_realloc_size(NULL, outbuf, osize + size);
                op = outbuf + offset;
                osize += size;
                oleft += size;
            } else {
                if (errno == EINVAL && (flags & MP_ICONV_ALLOW_CUTOFF)) {
                    // This is intended for cases where the input buffer is cut
                    // at a random byte position. If this happens in the middle
                    // of the buffer, it should still be an error. We say it's
                    // fine if the error is within 10 bytes of the end.
                    if (ileft <= 10)
                        break;
                }
                if (flags & MP_ICONV_VERBOSE) {
                    mp_err(log, "Error recoding text with codepage '%s'\n", cp);
                }
                talloc_free(outbuf);
                iconv_close(icdsc);
                goto failure;
            }
        } else if (clear)
            break;
    }

    iconv_close(icdsc);

    outbuf[osize - oleft - 1] = 0;
    return (bstr){outbuf, osize - oleft - 1};
#endif

failure:
    return (bstr){0};
}
コード例 #10
0
ファイル: drm_atomic.c プロジェクト: atomnuker/mpv
struct drm_atomic_context *drm_atomic_create_context(struct mp_log *log, int fd, int crtc_id,
                                                     int connector_id, int osd_plane_id, int video_plane_id)
{
    drmModePlaneRes *plane_res = NULL;
    drmModeRes *res = NULL;
    struct drm_object *plane = NULL;
    struct drm_atomic_context *ctx;
    int crtc_index = -1;
    int layercount = -1;
    int primary_id = 0;
    int overlay_id = 0;

    uint64_t value;

    res = drmModeGetResources(fd);
    if (!res) {
        mp_err(log, "Cannot retrieve DRM resources: %s\n", mp_strerror(errno));
        goto fail;
    }

    plane_res = drmModeGetPlaneResources(fd);
    if (!plane_res) {
        mp_err(log, "Cannot retrieve plane ressources: %s\n", mp_strerror(errno));
        goto fail;
    }

    ctx = talloc_zero(NULL, struct drm_atomic_context);
    if (!ctx) {
        mp_err(log, "Out of memory\n");
        goto fail;
    }

    ctx->fd = fd;
    ctx->crtc = drm_object_create(log, ctx->fd, crtc_id, DRM_MODE_OBJECT_CRTC);
    if (!ctx->crtc) {
        mp_err(log, "Failed to create CRTC object\n");
        goto fail;
    }

    for (int i = 0; i < res->count_crtcs; i++) {
        if (res->crtcs[i] == crtc_id) {
            crtc_index = i;
            break;
        }
    }

    for (int i = 0; i < res->count_connectors; i++) {
        drmModeConnector *connector = drmModeGetConnector(fd, res->connectors[i]);
        if (connector) {
            if (connector->connector_id == connector_id)
                ctx->connector =  drm_object_create(log, ctx->fd, connector->connector_id,
                                                    DRM_MODE_OBJECT_CONNECTOR);

            drmModeFreeConnector(connector);
            if (ctx->connector)
                break;
        }
    }

    for (unsigned int j = 0; j < plane_res->count_planes; j++) {

        drmModePlane *drmplane = drmModeGetPlane(ctx->fd, plane_res->planes[j]);
        const uint32_t possible_crtcs = drmplane->possible_crtcs;
        const uint32_t plane_id = drmplane->plane_id;
        drmModeFreePlane(drmplane);
        drmplane = NULL;

        if (possible_crtcs & (1 << crtc_index)) {
            plane = drm_object_create(log, ctx->fd, plane_id,
                                      DRM_MODE_OBJECT_PLANE);

            if (!plane) {
                mp_err(log, "Failed to create Plane object from plane ID %d\n",
                       plane_id);
                goto fail;
            }

            if (drm_object_get_property(plane, "TYPE", &value) == -EINVAL) {
                mp_err(log, "Unable to retrieve type property from plane %d\n", j);
                goto fail;
            }

            if (value != DRM_PLANE_TYPE_CURSOR) { // Skip cursor planes
                layercount++;

                if ((!primary_id) && (value == DRM_PLANE_TYPE_PRIMARY))
                    primary_id = plane_id;

                if ((!overlay_id) && (value == DRM_PLANE_TYPE_OVERLAY))
                    overlay_id = plane_id;

                if (layercount == osd_plane_id) {
                    ctx->osd_plane = plane;
                    continue;
                }

                if (layercount == video_plane_id) {
                    ctx->video_plane = plane;
                    continue;
                }
            }

            drm_object_free(plane);
            plane = NULL;
        }
    }

    // default OSD plane to primary if unspecified
    if (!ctx->osd_plane) {
        if (primary_id) {
            mp_verbose(log, "Using default plane %d for OSD\n", primary_id);
            ctx->osd_plane = drm_object_create(log, ctx->fd, primary_id, DRM_MODE_OBJECT_PLANE);
        } else {
            mp_err(log, "Failed to find OSD plane with id=%d\n", osd_plane_id);
            goto fail;
        }
    } else {
        mp_verbose(log, "Found OSD plane with ID %d\n", ctx->osd_plane->id);
    }

    // default video plane to overlay if unspecified
    if (!ctx->video_plane) {
        if (overlay_id) {
            mp_verbose(log, "Using default plane %d for video\n", overlay_id);
            ctx->video_plane = drm_object_create(log, ctx->fd, overlay_id, DRM_MODE_OBJECT_PLANE);
        } else {
            mp_verbose(log, "Failed to find video plane with id=%d. drmprime-drm hwdec interop will not work\n", video_plane_id);
        }
    } else {
        mp_verbose(log, "Found video plane with ID %d\n", ctx->video_plane->id);
    }

    drmModeFreePlaneResources(plane_res);
    drmModeFreeResources(res);
    return ctx;

fail:
    if (res)
        drmModeFreeResources(res);
    if (plane_res)
        drmModeFreePlaneResources(plane_res);
    if (plane)
        drm_object_free(plane);
    return NULL;
}
コード例 #11
0
ファイル: stream_dvb.c プロジェクト: AddictXQ/mpv
dvb_state_t *dvb_get_state(stream_t *stream)
{
    if (global_dvb_state != NULL) {
      return global_dvb_state;
    }
    struct mp_log *log = stream->log;
    struct mpv_global *global = stream->global;
    dvb_priv_t *priv = stream->priv;
    int type, size;
    char filename[30], *name;
    dvb_channels_list *list;
    dvb_card_config_t *cards = NULL, *tmp;
    dvb_state_t *state = NULL;

    state = malloc(sizeof(dvb_state_t));
    if (state == NULL)
        return NULL;

    state->count = 0;
    state->switching_channel = false;
    state->stream_used = true;
    state->cards = NULL;
    state->fe_fd = state->dvr_fd = -1;
    for (int i = 0; i < MAX_CARDS; i++) {
        snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/frontend0", i);
        int fd = open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
        if (fd < 0) {
            mp_verbose(log, "DVB_CONFIG, can't open device %s, skipping\n",
                       filename);
            continue;
        }

        mp_verbose(log, "Opened device %s, FD: %d\n", filename, fd);
        int* tuner_types = NULL;
        int num_tuner_types = dvb_get_tuner_types(fd, log, &tuner_types);
        close(fd);
        mp_verbose(log, "Frontend device %s offers %d supported delivery systems.\n",
                   filename, num_tuner_types);
        for (int num_tuner_type=0; num_tuner_type<num_tuner_types; num_tuner_type++) {
          type = tuner_types[num_tuner_type];
          if (type != TUNER_SAT && type != TUNER_TER && type != TUNER_CBL &&
              type != TUNER_ATSC) {
            mp_verbose(log, "DVB_CONFIG, can't detect tuner type of "
                       "card %d, skipping\n", i);
            continue;
          }

          void *talloc_ctx = talloc_new(NULL);
          char *conf_file = NULL;
          if (priv->cfg_file && priv->cfg_file[0])
            conf_file = priv->cfg_file;
          else {
            switch (type) {
            case TUNER_TER:
              conf_file = mp_find_config_file(talloc_ctx, global,
                                              "channels.conf.ter");
              break;
            case TUNER_CBL:
              conf_file = mp_find_config_file(talloc_ctx, global,
                                              "channels.conf.cbl");
              break;
            case TUNER_SAT:
              conf_file = mp_find_config_file(talloc_ctx, global,
                                              "channels.conf.sat");
              break;
            case TUNER_ATSC:
              conf_file = mp_find_config_file(talloc_ctx, global,
                                              "channels.conf.atsc");
              break;
            }
            if (conf_file) {
              mp_verbose(log, "Ignoring other channels.conf files.\n");
            } else {
              conf_file = mp_find_config_file(talloc_ctx, global,
                                              "channels.conf");
            }
          }

          list = dvb_get_channels(log, priv->cfg_full_transponder, conf_file,
                                  type);
          talloc_free(talloc_ctx);

          if (list == NULL)
            continue;

          size = sizeof(dvb_card_config_t) * (state->count + 1);
          tmp = realloc(state->cards, size);

          if (tmp == NULL) {
            mp_err(log, "DVB_CONFIG, can't realloc %d bytes, skipping\n",
                   size);
            free(list);
            continue;
          }
          cards = tmp;

          name = malloc(20);
          if (name == NULL) {
            mp_err(log, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
            free(list);
            free(tmp);
            continue;
          }

          state->cards = cards;
          state->cards[state->count].devno = i;
          state->cards[state->count].list = list;
          state->cards[state->count].type = type;
          snprintf(name, 20, "DVB-%c card n. %d",
                   type == TUNER_TER ? 'T' : (type == TUNER_CBL ? 'C' : 'S'),
                   state->count + 1);
          state->cards[state->count].name = name;
          state->count++;
        }
        talloc_free(tuner_types);
    }

    if (state->count == 0) {
        free(state);
        state = NULL;
    }

    global_dvb_state = state;
    return state;
}
コード例 #12
0
ファイル: image_writer.c プロジェクト: jmglogow/mpv
struct mp_image *convert_image(struct mp_image *image, int destfmt,
                               struct mp_log *log)
{
    int d_w, d_h;
    mp_image_params_get_dsize(&image->params, &d_w, &d_h);

    struct mp_image_params p = {
        .imgfmt = destfmt,
        .w = d_w,
        .h = d_h,
        .p_w = 1,
        .p_h = 1,
    };
    mp_image_params_guess_csp(&p);

    // If RGB, just assume everything is correct.
    if (p.color.space != MP_CSP_RGB) {
        // Currently, assume what FFmpeg's jpg encoder needs.
        // Of course this works only for non-HDR (no HDR support in libswscale).
        p.color.levels = MP_CSP_LEVELS_PC;
        p.color.space = MP_CSP_BT_601;
        p.chroma_location = MP_CHROMA_CENTER;
        mp_image_params_guess_csp(&p);
    }

    if (mp_image_params_equal(&p, &image->params))
        return mp_image_new_ref(image);

    struct mp_image *dst = mp_image_alloc(p.imgfmt, p.w, p.h);
    if (!dst) {
        mp_err(log, "Out of memory.\n");
        return NULL;
    }
    mp_image_copy_attributes(dst, image);

    dst->params = p;

    if (mp_image_swscale(dst, image, mp_sws_hq_flags) < 0) {
        mp_err(log, "Error when converting image.\n");
        talloc_free(dst);
        return NULL;
    }

    return dst;
}

bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
                const char *filename, struct mp_log *log)
{
    struct image_writer_opts defs = image_writer_opts_defaults;
    if (!opts)
        opts = &defs;

    struct image_writer_ctx ctx = { log, opts, image->fmt };
    bool (*write)(struct image_writer_ctx *, mp_image_t *, FILE *) = write_lavc;
    int destfmt = 0;

#if HAVE_JPEG
    if (opts->format == AV_CODEC_ID_MJPEG) {
        write = write_jpeg;
        destfmt = IMGFMT_RGB24;
    }
#endif

    if (!destfmt)
        destfmt = get_target_format(&ctx);

    struct mp_image *dst = convert_image(image, destfmt, log);
    if (!dst)
        return false;

    FILE *fp = fopen(filename, "wb");
    bool success = false;
    if (fp == NULL) {
        mp_err(log, "Error opening '%s' for writing!\n", filename);
    } else {
        success = write(&ctx, dst, fp);
        success = !fclose(fp) && success;
        if (!success)
            mp_err(log, "Error writing file '%s'!\n", filename);
    }

    talloc_free(dst);
    return success;
}

void dump_png(struct mp_image *image, const char *filename, struct mp_log *log)
{
    struct image_writer_opts opts = image_writer_opts_defaults;
    opts.format = AV_CODEC_ID_PNG;
    write_image(image, &opts, filename, log);
}