Ejemplo n.º 1
0
int dvb_get_tuner_type(int fe_fd, struct mp_log *log)
{
    struct dvb_frontend_info fe_info;
    int 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;
    }

}
Ejemplo n.º 2
0
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 demuxer_params p = {.force_format = "playlist"};
    struct demuxer *d = demux_open_url(file, &p, NULL, global);
    if (!d) {
        talloc_free(log);
        return NULL;
    }

    struct playlist *ret = NULL;
    if (d && d->playlist) {
        ret = talloc_zero(NULL, struct playlist);
        playlist_transfer_entries(ret, d->playlist);
        if (d->filetype && strcmp(d->filetype, "hls") == 0) {
            mp_warn(log, "This might be a HLS stream. For correct operation, "
                         "pass it to the player\ndirectly. Don't use --playlist.\n");
        }
    }
    free_demuxer_and_stream(d);

    if (ret) {
        mp_verbose(log, "Playlist successfully parsed\n");
    } else {
        mp_err(log, "Error while parsing playlist\n");
    }

    if (ret && !ret->first)
        mp_warn(log, "Warning: empty playlist\n");

    talloc_free(log);
    return ret;
}
Ejemplo n.º 3
0
void mp_ass_configure_fonts(ASS_Renderer *priv, struct osd_style_opts *opts,
                            struct mpv_global *global, struct mp_log *log)
{
    void *tmp = talloc_new(NULL);
    char *default_font = mp_find_user_config_file(tmp, global, "subfont.ttf");
    char *config       = mp_find_config_file(tmp, global, "fonts.conf");

    if (default_font && !mp_path_exists(default_font))
        default_font = NULL;

    mp_verbose(log, "Setting up fonts...\n");
    ass_set_fonts(priv, default_font, opts->font, 1, config, 1);
    mp_verbose(log, "Done.\n");

    talloc_free(tmp);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
void mp_set_avcodec_threads(struct mp_log *l, AVCodecContext *avctx, int threads)
{
    if (threads == 0) {
        threads = av_cpu_count();
        if (threads < 1) {
            mp_warn(l, "Could not determine thread count to use, defaulting to 1.\n");
            threads = 1;
        } else {
            mp_verbose(l, "Detected %d logical cores.\n", threads);
            if (threads > 1)
                threads += 1; // extra thread for better load balancing
        }
        // Apparently some libavcodec versions have or had trouble with more
        // than 16 threads, and/or print a warning when using > 16.
        threads = MPMIN(threads, 16);
    }
    mp_verbose(l, "Requesting %d threads for decoding.\n", threads);
    avctx->thread_count = threads;
}
Ejemplo n.º 6
0
static bool add_volume(struct mp_log *log, struct mp_archive *mpa,
                       struct stream *src, const char* url)
{
    struct mp_archive_volume *vol = talloc_zero(mpa, struct mp_archive_volume);
    mp_verbose(log, "Adding volume %s\n", url);
    vol->mpa = mpa;
    vol->src = src;
    vol->url = talloc_strdup(vol, url);
    return archive_read_append_callback_data(mpa->arch, vol) == ARCHIVE_OK;
}
Ejemplo n.º 7
0
static VADisplay *create_native_va_display(struct ra *ra, struct mp_log *log)
{
    for (int n = 0; n < MP_ARRAY_SIZE(create_native_cbs); n++) {
        const struct va_create_native *disp = &create_native_cbs[n];
        mp_verbose(log, "Trying to open a %s VA display...\n", disp->name);
        VADisplay *display = disp->create(ra);
        if (display)
            return display;
    }
    return NULL;
}
Ejemplo n.º 8
0
void mp_get_src_dst_rects(struct mp_log *log, struct mp_vo_opts *opts,
                          int vo_caps, struct mp_image_params *video,
                          int window_w, int window_h, double monitor_par,
                          struct mp_rect *out_src,
                          struct mp_rect *out_dst,
                          struct mp_osd_res *out_osd)
{
    int src_w = video->w;
    int src_h = video->h;
    int src_dw, src_dh;
    mp_image_params_get_dsize(video, &src_dw, &src_dh);
    if (video->rotate % 180 == 90 && (vo_caps & VO_CAP_ROTATE90)) {
        MPSWAP(int, src_w, src_h);
        MPSWAP(int, src_dw, src_dh);
    }
    window_w = MPMAX(1, window_w);
    window_h = MPMAX(1, window_h);
    struct mp_rect dst = {0, 0, window_w, window_h};
    struct mp_rect src = {0, 0, src_w,    src_h};
    struct mp_osd_res osd = {
        .w = window_w,
        .h = window_h,
        .display_par = monitor_par,
    };
    if (opts->keepaspect) {
        int scaled_width, scaled_height;
        aspect_calc_panscan(log, opts, src_w, src_h, src_dw, src_dh,
                            window_w, window_h, monitor_par,
                            &scaled_width, &scaled_height);
        src_dst_split_scaling(src_w, window_w, scaled_width, opts->unscaled,
                              opts->zoom, opts->align_x, opts->pan_x,
                              &src.x0, &src.x1, &dst.x0, &dst.x1,
                              &osd.ml, &osd.mr);
        src_dst_split_scaling(src_h, window_h, scaled_height, opts->unscaled,
                              opts->zoom, opts->align_y, opts->pan_y,
                              &src.y0, &src.y1, &dst.y0, &dst.y1,
                              &osd.mt, &osd.mb);
    }

    *out_src = src;
    *out_dst = dst;
    *out_osd = osd;

    int sw = src.x1 - src.x0, sh = src.y1 - src.y0;
    int dw = dst.x1 - dst.x0, dh = dst.y1 - dst.y0;

    mp_verbose(log, "Window size: %dx%d\n",
               window_w, window_h);
    mp_verbose(log, "Video source: %dx%d (%d:%d)\n",
               video->w, video->h, video->p_w, video->p_h);
    mp_verbose(log, "Video display: (%d, %d) %dx%d -> (%d, %d) %dx%d\n",
               src.x0, src.y0, sw, sh, dst.x0, dst.y0, dw, dh);
    mp_verbose(log, "Video scale: %f/%f\n",
               (double)dw / sw, (double)dh / sh);
    mp_verbose(log, "OSD borders: l=%d t=%d r=%d b=%d\n",
               osd.ml, osd.mt, osd.mr, osd.mb);
    mp_verbose(log, "Video borders: l=%d t=%d r=%d b=%d\n",
               dst.x0, dst.y0, window_w - dst.x1, window_h - dst.y1);
}
Ejemplo n.º 9
0
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);
    }
Ejemplo n.º 10
0
static bool parse_pid_string(struct mp_log *log, char *pid_string,
                             dvb_channel_t *ptr)
{
    if (pid_string[0]) {
        int pcnt = 0;
        /* These tokens also catch vdr-style PID lists.
         * They can contain 123=deu@3,124=eng+jap@4;125
         * 3 and 4 are codes for codec type, =langLeft+langRight is allowed,
         * and ; may separate a dolby channel.
         * With the numChars-test and the full token-list, all is handled
         * gracefully.
         */
        const char *tokens = "+,;";
        char *pidPart;
        char *savePtr = NULL;
        pidPart = dvb_strtok_r(pid_string, tokens, &savePtr);
        while (pidPart != NULL) {
            if (ptr->pids_cnt >= DMX_FILTER_SIZE - 1) {
                mp_verbose(log, "Maximum number of PIDs for one channel "
                                "reached, ignoring further ones!\n");
                return pcnt > 0;
            }
            int numChars = 0;
            int pid = 0;
            pcnt += sscanf(pidPart, "%d%n", &pid, &numChars);
            if (numChars > 0) {
                ptr->pids[ptr->pids_cnt] = pid;
                ptr->pids_cnt++;
            }
            pidPart = dvb_strtok_r(NULL, tokens, &savePtr);
        }
        if (pcnt > 0)
            return true;
    }
    return false;
}
Ejemplo n.º 11
0
static dvb_channels_list *dvb_get_channels(struct mp_log *log, char *filename, int type)
{
        dvb_channels_list  *list;
        FILE *f;
        char line[CHANNEL_LINE_LEN], *colon;

        if (!filename)
            return NULL;

        int fields, cnt, pcnt, k;
        int has8192, has0;
        dvb_channel_t *ptr, *tmp, chn;
        char tmp_lcr[256], tmp_hier[256], inv[256], bw[256], cr[256], mod[256], transm[256], gi[256], vpid_str[256], apid_str[256];
        const char *cbl_conf = "%d:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
        const char *sat_conf = "%d:%c:%d:%d:%255[^:]:%255[^:]\n";
        const char *ter_conf = "%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
        const char *atsc_conf = "%d:%255[^:]:%255[^:]:%255[^:]\n";

        mp_verbose(log, "CONFIG_READ FILE: %s, type: %d\n", filename, type);
        if((f=fopen(filename, "r"))==NULL)
        {
                mp_fatal(log, "CAN'T READ CONFIG FILE %s\n", filename);
                return NULL;
        }

        list = malloc(sizeof(dvb_channels_list));
        if(list == NULL)
        {
                fclose(f);
                mp_verbose(log, "DVB_GET_CHANNELS: couldn't malloc enough memory\n");
                return NULL;
        }

        ptr = &chn;
        list->NUM_CHANNELS = 0;
        list->channels = NULL;
        while(! feof(f))
        {
                if( fgets(line, CHANNEL_LINE_LEN, f) == NULL )
                        continue;

                if((line[0] == '#') || (strlen(line) == 0))
                        continue;

                colon = strchr(line, ':');
                if(colon)
                {
                        k = colon - line;
                        if(!k)
                                continue;
                        ptr->name = malloc(k+1);
                        if(! ptr->name)
                                continue;
                        av_strlcpy(ptr->name, line, k+1);
                }
                else
                        continue;
                k++;
                apid_str[0] = vpid_str[0] = 0;
                ptr->pids_cnt = 0;
                ptr->freq = 0;
                if(type == TUNER_TER)
                {
                        fields = sscanf(&line[k], ter_conf,
                                &ptr->freq, inv, bw, cr, tmp_lcr, mod,
                                transm, gi, tmp_hier, vpid_str, apid_str);
                        mp_verbose(log, "TER, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d",
                                list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
                }
                else if(type == TUNER_CBL)
                {
                        fields = sscanf(&line[k], cbl_conf,
                                &ptr->freq, inv, &ptr->srate,
                                cr, mod, vpid_str, apid_str);
                        mp_verbose(log, "CBL, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d",
                                list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate);
                }
#ifdef DVB_ATSC
                else if(type == TUNER_ATSC)
                {
                        fields = sscanf(&line[k], atsc_conf,
                                 &ptr->freq, mod, vpid_str, apid_str);
                        mp_verbose(log, "ATSC, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d\n",
                                list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
                }
#endif
                else //SATELLITE
                {
                        fields = sscanf(&line[k], sat_conf,
                                &ptr->freq, &ptr->pol, &ptr->diseqc, &ptr->srate, vpid_str, apid_str);
                        ptr->pol = toupper(ptr->pol);
                        ptr->freq *=  1000UL;
                        ptr->srate *=  1000UL;
                        ptr->tone = -1;
                        ptr->inv = INVERSION_AUTO;
                        ptr->cr = FEC_AUTO;
                        if((ptr->diseqc > 4) || (ptr->diseqc < 0))
                            continue;
                        if(ptr->diseqc > 0)
                            ptr->diseqc--;
                        mp_verbose(log, "SAT, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, SRATE: %d, POL: %c, DISEQC: %d",
                                list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate, ptr->pol, ptr->diseqc);
                }

                if(vpid_str[0])
                {
                        pcnt = sscanf(vpid_str, "%d+%d+%d+%d+%d+%d+%d", &ptr->pids[0], &ptr->pids[1], &ptr->pids[2], &ptr->pids[3],
                                &ptr->pids[4], &ptr->pids[5], &ptr->pids[6]);
                        if(pcnt > 0)
                        {
                                ptr->pids_cnt = pcnt;
                                fields++;
                        }
                }

                if(apid_str[0])
                {
                        cnt = ptr->pids_cnt;
                        pcnt = sscanf(apid_str, "%d+%d+%d+%d+%d+%d+%d+%d", &ptr->pids[cnt], &ptr->pids[cnt+1], &ptr->pids[cnt+2],
                                &ptr->pids[cnt+3], &ptr->pids[cnt+4], &ptr->pids[cnt+5], &ptr->pids[cnt+6], &ptr->pids[cnt+7]);
                        if(pcnt > 0)
                        {
                                ptr->pids_cnt += pcnt;
                                fields++;
                        }
                }

                if((fields < 2) || (ptr->pids_cnt <= 0) || (ptr->freq == 0) || (strlen(ptr->name) == 0))
                        continue;

                has8192 = has0 = 0;
                for(cnt = 0; cnt < ptr->pids_cnt; cnt++)
                {
                        if(ptr->pids[cnt] == 8192)
                                has8192 = 1;
                        if(ptr->pids[cnt] == 0)
                                has0 = 1;
                }
                if(has8192)
                {
                        ptr->pids[0] = 8192;
                        ptr->pids_cnt = 1;
                }
                else if(! has0)
                {
                        ptr->pids[ptr->pids_cnt] = 0;   //PID 0 is the PAT
                        ptr->pids_cnt++;
                }
                mp_verbose(log, " PIDS: ");
                for(cnt = 0; cnt < ptr->pids_cnt; cnt++)
                        mp_verbose(log, " %d ", ptr->pids[cnt]);
                mp_verbose(log, "\n");

                if((type == TUNER_TER) || (type == TUNER_CBL))
                {
                        if(! strcmp(inv, "INVERSION_ON"))
                                ptr->inv = INVERSION_ON;
                        else if(! strcmp(inv, "INVERSION_OFF"))
                                ptr->inv = INVERSION_OFF;
                        else
                                ptr->inv = INVERSION_AUTO;


                        if(! strcmp(cr, "FEC_1_2"))
                                ptr->cr =FEC_1_2;
                        else if(! strcmp(cr, "FEC_2_3"))
                                ptr->cr =FEC_2_3;
                        else if(! strcmp(cr, "FEC_3_4"))
                                ptr->cr =FEC_3_4;
                        else if(! strcmp(cr, "FEC_4_5"))
                                ptr->cr =FEC_4_5;
                        else if(! strcmp(cr, "FEC_6_7"))
                                ptr->cr =FEC_6_7;
                        else if(! strcmp(cr, "FEC_8_9"))
                                ptr->cr =FEC_8_9;
                        else if(! strcmp(cr, "FEC_5_6"))
                                ptr->cr =FEC_5_6;
                        else if(! strcmp(cr, "FEC_7_8"))
                                ptr->cr =FEC_7_8;
                        else if(! strcmp(cr, "FEC_NONE"))
                                ptr->cr =FEC_NONE;
                        else ptr->cr =FEC_AUTO;
                }


                if((type == TUNER_TER) || (type == TUNER_CBL) || (type == TUNER_ATSC))
                {
                        if(! strcmp(mod, "QAM_128"))
                                ptr->mod = QAM_128;
                        else if(! strcmp(mod, "QAM_256"))
                                ptr->mod = QAM_256;
                        else if(! strcmp(mod, "QAM_64"))
                                ptr->mod = QAM_64;
                        else if(! strcmp(mod, "QAM_32"))
                                ptr->mod = QAM_32;
                        else if(! strcmp(mod, "QAM_16"))
                                ptr->mod = QAM_16;
#ifdef DVB_ATSC
                        else if(! strcmp(mod, "VSB_8") || ! strcmp(mod, "8VSB"))
                                ptr->mod = VSB_8;
                        else if(! strcmp(mod, "VSB_16") || !strcmp(mod, "16VSB"))
                                ptr->mod = VSB_16;
                        else if(! strcmp(mod, "QAM_AUTO"))
                                ptr->mod = QAM_AUTO;

#endif
                }

                if(type == TUNER_TER)
                {
                        if(! strcmp(bw, "BANDWIDTH_6_MHZ"))
                                ptr->bw = BANDWIDTH_6_MHZ;
                        else if(! strcmp(bw, "BANDWIDTH_7_MHZ"))
                                ptr->bw = BANDWIDTH_7_MHZ;
                        else if(! strcmp(bw, "BANDWIDTH_8_MHZ"))
                                ptr->bw = BANDWIDTH_8_MHZ;


                        if(! strcmp(transm, "TRANSMISSION_MODE_2K"))
                                ptr->trans = TRANSMISSION_MODE_2K;
                        else if(! strcmp(transm, "TRANSMISSION_MODE_8K"))
                                ptr->trans = TRANSMISSION_MODE_8K;
                        else if(! strcmp(transm, "TRANSMISSION_MODE_AUTO"))
                                ptr->trans = TRANSMISSION_MODE_AUTO;

                        if(! strcmp(gi, "GUARD_INTERVAL_1_32"))
                                ptr->gi = GUARD_INTERVAL_1_32;
                        else if(! strcmp(gi, "GUARD_INTERVAL_1_16"))
                                ptr->gi = GUARD_INTERVAL_1_16;
                        else if(! strcmp(gi, "GUARD_INTERVAL_1_8"))
                                ptr->gi = GUARD_INTERVAL_1_8;
                        else if(! strcmp(gi, "GUARD_INTERVAL_1_4"))
                                ptr->gi = GUARD_INTERVAL_1_4;
                        else ptr->gi = GUARD_INTERVAL_AUTO;

                        if(! strcmp(tmp_lcr, "FEC_1_2"))
                                ptr->cr_lp =FEC_1_2;
                        else if(! strcmp(tmp_lcr, "FEC_2_3"))
                                ptr->cr_lp =FEC_2_3;
                        else if(! strcmp(tmp_lcr, "FEC_3_4"))
                                ptr->cr_lp =FEC_3_4;
                        else if(! strcmp(tmp_lcr, "FEC_4_5"))
                                ptr->cr_lp =FEC_4_5;
                        else if(! strcmp(tmp_lcr, "FEC_6_7"))
                                ptr->cr_lp =FEC_6_7;
                        else if(! strcmp(tmp_lcr, "FEC_8_9"))
                                ptr->cr_lp =FEC_8_9;
                        else if(! strcmp(tmp_lcr, "FEC_5_6"))
                                ptr->cr_lp =FEC_5_6;
                        else if(! strcmp(tmp_lcr, "FEC_7_8"))
                                ptr->cr_lp =FEC_7_8;
                        else if(! strcmp(tmp_lcr, "FEC_NONE"))
                                ptr->cr_lp =FEC_NONE;
                        else ptr->cr_lp =FEC_AUTO;


                        if(! strcmp(tmp_hier, "HIERARCHY_1"))
                                ptr->hier = HIERARCHY_1;
                        else if(! strcmp(tmp_hier, "HIERARCHY_2"))
                                ptr->hier = HIERARCHY_2;
                        else if(! strcmp(tmp_hier, "HIERARCHY_4"))
                                ptr->hier = HIERARCHY_4;
                        else if(! strcmp(tmp_hier, "HIERARCHY_AUTO"))
                                ptr->hier = HIERARCHY_AUTO;
                        else    ptr->hier = HIERARCHY_NONE;
                }

                tmp = realloc(list->channels, sizeof(dvb_channel_t) * (list->NUM_CHANNELS + 1));
                if(tmp == NULL)
                        break;

                list->channels = tmp;
                memcpy(&(list->channels[list->NUM_CHANNELS]), ptr, sizeof(dvb_channel_t));
                list->NUM_CHANNELS++;
                if(sizeof(dvb_channel_t) * list->NUM_CHANNELS >= 1024*1024)
                {
                        mp_verbose(log, "dvbin.c, > 1MB allocated for channels struct, dropping the rest of the file\r\n");
                        break;
                }
        }

        fclose(f);
        if(list->NUM_CHANNELS == 0)
        {
                free(list->channels);
                free(list);
                return NULL;
        }

        list->current = 0;
        return list;
}
Ejemplo n.º 12
0
static dvb_channels_list *dvb_get_channels(struct mp_log *log,
                                           int cfg_full_transponder,
                                           char *filename,
                                           int type)
{
    dvb_channels_list *list;
    FILE *f;
    char line[CHANNEL_LINE_LEN], *colon;

    if (!filename)
        return NULL;

    int fields, cnt, k;
    int has8192, has0;
    dvb_channel_t *ptr, *tmp, chn;
    char tmp_lcr[256], tmp_hier[256], inv[256], bw[256], cr[256], mod[256],
         transm[256], gi[256], vpid_str[256], apid_str[256], tpid_str[256],
         vdr_par_str[256], vdr_loc_str[256];
    const char *cbl_conf =
        "%d:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
    const char *sat_conf = "%d:%c:%d:%d:%255[^:]:%255[^:]\n";
    const char *ter_conf =
        "%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n";
    const char *atsc_conf = "%d:%255[^:]:%255[^:]:%255[^:]\n";

    const char *vdr_conf =
        "%d:%255[^:]:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%*255[^:]:%d:%*d:%*d:%*d\n%n";

    mp_verbose(log, "CONFIG_READ FILE: %s, type: %d\n", filename, type);
    if ((f = fopen(filename, "r")) == NULL) {
        mp_fatal(log, "CAN'T READ CONFIG FILE %s\n", filename);
        return NULL;
    }

    list = malloc(sizeof(dvb_channels_list));
    if (list == NULL) {
        fclose(f);
        mp_verbose(log, "DVB_GET_CHANNELS: couldn't malloc enough memory\n");
        return NULL;
    }

    ptr = &chn;
    list->NUM_CHANNELS = 0;
    list->channels = NULL;
    while (!feof(f)) {
        if (fgets(line, CHANNEL_LINE_LEN, f) == NULL)
            continue;

        if ((line[0] == '#') || (strlen(line) == 0))
            continue;

        colon = strchr(line, ':');
        if (colon) {
            k = colon - line;
            if (!k)
                continue;
            // In some modern VDR-style configs, channel name also has bouquet after ;.
            // Parse that off, we ignore it.
            char *bouquet_sep = strchr(line, ';');
            int channel_name_length = k;
            if (bouquet_sep && bouquet_sep < colon)
                channel_name_length = bouquet_sep - line;
            ptr->name = malloc(channel_name_length + 1);
            if (!ptr->name)
                continue;
            av_strlcpy(ptr->name, line, channel_name_length + 1);
        } else {
            continue;
        }
        k++;
        vpid_str[0] = apid_str[0] = tpid_str[0] = 0;
        vdr_loc_str[0] = vdr_par_str[0] = 0;
        ptr->pids_cnt = 0;
        ptr->freq = 0;
        ptr->is_dvb_s2 = false;
        ptr->service_id = -1;
        ptr->stream_id = NO_STREAM_ID_FILTER;
        ptr->inv = INVERSION_AUTO;

        // Check if VDR-type channels.conf-line - then full line is consumed by the scan.
        int num_chars = 0;
        fields = sscanf(&line[k], vdr_conf,
                        &ptr->freq, vdr_par_str, vdr_loc_str, &ptr->srate,
                        vpid_str, apid_str, tpid_str, &ptr->service_id,
                        &num_chars);

        if (num_chars == strlen(&line[k])) {
            // It's a VDR-style config line.
            parse_vdr_par_string(vdr_par_str, ptr);
            // We still need the special SAT-handling here.
            if (type != TUNER_TER && type != TUNER_CBL && type != TUNER_ATSC) {
                ptr->freq *=  1000UL;
                ptr->srate *=  1000UL;
                ptr->tone = -1;
                ptr->inv = INVERSION_AUTO;
                ptr->cr = FEC_AUTO;

                if (vdr_loc_str[0]) {
                    // In older vdr config format, this field contained the DISEQc information.
                    // If it is numeric, assume that's it.
                    int diseqc_info = 0;
                    int valid_digits = 0;
                    if (sscanf(vdr_loc_str, "%d%n", &diseqc_info,
                               &valid_digits) == 1)
                    {
                        if (valid_digits == strlen(vdr_loc_str)) {
                            ptr->diseqc = diseqc_info;
                            if ((ptr->diseqc > 4) || (ptr->diseqc < 0))
                                continue;
                            if (ptr->diseqc > 0)
                                ptr->diseqc--;
                        }
                    }
                }

                mp_verbose(log, "SAT, NUM: %d, NUM_FIELDS: %d, NAME: %s, "
                           "FREQ: %d, SRATE: %d, POL: %c, DISEQC: %d, S2: %s, "
                           "StreamID: %d, SID: %d", list->NUM_CHANNELS,
                           fields, ptr->name, ptr->freq, ptr->srate, ptr->pol,
                           ptr->diseqc, ptr->is_dvb_s2 ? "yes" : "no",
                           ptr->stream_id, ptr->service_id);
            } else {
                mp_verbose(log, "VDR, NUM: %d, NUM_FIELDS: %d, NAME: %s, "
                           "FREQ: %d, SRATE: %d", list->NUM_CHANNELS, fields,
                           ptr->name, ptr->freq, ptr->srate);
            }
        } else if (type == TUNER_TER) {
            fields = sscanf(&line[k], ter_conf,
                            &ptr->freq, inv, bw, cr, tmp_lcr, mod,
                            transm, gi, tmp_hier, vpid_str, apid_str);
            mp_verbose(log, "TER, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d",
                       list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
        } else if (type == TUNER_CBL) {
            fields = sscanf(&line[k], cbl_conf,
                            &ptr->freq, inv, &ptr->srate,
                            cr, mod, vpid_str, apid_str);
            mp_verbose(log, "CBL, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, "
                       "SRATE: %d", list->NUM_CHANNELS, fields, ptr->name,
                       ptr->freq, ptr->srate);
        }
#ifdef DVB_ATSC
        else if (type == TUNER_ATSC) {
            fields = sscanf(&line[k], atsc_conf,
                            &ptr->freq, mod, vpid_str, apid_str);
            mp_verbose(log, "ATSC, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d\n",
                       list->NUM_CHANNELS, fields, ptr->name, ptr->freq);
        }
#endif
        else {       //SATELLITE
            fields = sscanf(&line[k], sat_conf,
                            &ptr->freq, &ptr->pol, &ptr->diseqc, &ptr->srate,
                            vpid_str,
                            apid_str);
            ptr->pol = mp_toupper(ptr->pol);
            ptr->freq *=  1000UL;
            ptr->srate *=  1000UL;
            ptr->tone = -1;
            ptr->inv = INVERSION_AUTO;
            ptr->cr = FEC_AUTO;
            if ((ptr->diseqc > 4) || (ptr->diseqc < 0))
                continue;
            if (ptr->diseqc > 0)
                ptr->diseqc--;
            mp_verbose(log, "SAT, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, "
                       "SRATE: %d, POL: %c, DISEQC: %d",
                       list->NUM_CHANNELS, fields, ptr->name, ptr->freq,
                       ptr->srate, ptr->pol, ptr->diseqc);
        }

        if (parse_pid_string(log, vpid_str, ptr))
            fields++;
        if (parse_pid_string(log, apid_str, ptr))
            fields++;
                 /* If we do not know the service_id, PMT can not be extracted.
                    Teletext decoding will fail without PMT. */
        if (ptr->service_id != -1) {
            if (parse_pid_string(log, tpid_str, ptr))
                fields++;
        }


        if ((fields < 2) || (ptr->pids_cnt <= 0) || (ptr->freq == 0) ||
            (strlen(ptr->name) == 0))
            continue;

        /* Add some PIDs which are mandatory in DVB,
         * and contain human-readable helpful data. */

        /* This is the STD, the service description table.
         * It contains service names and such, ffmpeg decodes it. */
        ptr->pids[ptr->pids_cnt] = 0x0011;
        ptr->pids_cnt++;

        /* This is the EIT, which contains EPG data.
         * ffmpeg can not decode it (yet), but e.g. VLC
         * shows what was recorded. */
        ptr->pids[ptr->pids_cnt] = 0x0012;
        ptr->pids_cnt++;

        if (ptr->service_id != -1) {
            /* We have the PMT-PID in addition.
               This will be found later, when we tune to the channel.
               Push back here to create the additional demux. */
            ptr->pids[ptr->pids_cnt] = -1;       // Placeholder.
            ptr->pids_cnt++;
        }

        has8192 = has0 = 0;
        for (cnt = 0; cnt < ptr->pids_cnt; cnt++) {
            if (ptr->pids[cnt] == 8192)
                has8192 = 1;
            if (ptr->pids[cnt] == 0)
                has0 = 1;
        }

        /* 8192 is the pseudo-PID for full TP dump,
           enforce that if requested. */
        if (!has8192 && cfg_full_transponder)
            has8192 = 1;
        if (has8192) {
            ptr->pids[0] = 8192;
            ptr->pids_cnt = 1;
        } else if (!has0) {
            ptr->pids[ptr->pids_cnt] = 0;               //PID 0 is the PAT
            ptr->pids_cnt++;
        }

        mp_verbose(log, " PIDS: ");
        for (cnt = 0; cnt < ptr->pids_cnt; cnt++)
            mp_verbose(log, " %d ", ptr->pids[cnt]);
        mp_verbose(log, "\n");

        if ((type == TUNER_TER) || (type == TUNER_CBL)) {
            if (!strcmp(inv, "INVERSION_ON")) {
                ptr->inv = INVERSION_ON;
            } else if (!strcmp(inv, "INVERSION_OFF")) {
                ptr->inv = INVERSION_OFF;
            } else {
                ptr->inv = INVERSION_AUTO;
            }


            if (!strcmp(cr, "FEC_1_2")) {
                ptr->cr = FEC_1_2;
            } else if (!strcmp(cr, "FEC_2_3")) {
                ptr->cr = FEC_2_3;
            } else if (!strcmp(cr, "FEC_3_4")) {
                ptr->cr = FEC_3_4;
            } else if (!strcmp(cr, "FEC_4_5")) {
                ptr->cr = FEC_4_5;
            } else if (!strcmp(cr, "FEC_6_7")) {
                ptr->cr = FEC_6_7;
            } else if (!strcmp(cr, "FEC_8_9")) {
                ptr->cr = FEC_8_9;
            } else if (!strcmp(cr, "FEC_5_6")) {
                ptr->cr = FEC_5_6;
            } else if (!strcmp(cr, "FEC_7_8")) {
                ptr->cr = FEC_7_8;
            } else if (!strcmp(cr, "FEC_NONE")) {
                ptr->cr = FEC_NONE;
            } else {
                ptr->cr = FEC_AUTO;
            }
        }


        if (type == TUNER_TER || type == TUNER_CBL || type == TUNER_ATSC) {
            if (!strcmp(mod, "QAM_128")) {
                ptr->mod = QAM_128;
            } else if (!strcmp(mod, "QAM_256")) {
                ptr->mod = QAM_256;
            } else if (!strcmp(mod, "QAM_64")) {
                ptr->mod = QAM_64;
            } else if (!strcmp(mod, "QAM_32")) {
                ptr->mod = QAM_32;
            } else if (!strcmp(mod, "QAM_16")) {
                ptr->mod = QAM_16;
#ifdef DVB_ATSC
            } else if (!strcmp(mod, "VSB_8") || !strcmp(mod, "8VSB")) {
                ptr->mod = VSB_8;
            } else if (!strcmp(mod, "VSB_16") || !strcmp(mod, "16VSB")) {
                ptr->mod = VSB_16;
            } else if (!strcmp(mod, "QAM_AUTO")) {
                ptr->mod = QAM_AUTO;
            }

#endif
        }

        if (type == TUNER_TER) {
            if (!strcmp(bw, "BANDWIDTH_6_MHZ")) {
                ptr->bw = BANDWIDTH_6_MHZ;
            } else if (!strcmp(bw, "BANDWIDTH_7_MHZ")) {
                ptr->bw = BANDWIDTH_7_MHZ;
            } else if (!strcmp(bw, "BANDWIDTH_8_MHZ")) {
                ptr->bw = BANDWIDTH_8_MHZ;
            }


            if (!strcmp(transm, "TRANSMISSION_MODE_2K")) {
                ptr->trans = TRANSMISSION_MODE_2K;
            } else if (!strcmp(transm, "TRANSMISSION_MODE_8K")) {
                ptr->trans = TRANSMISSION_MODE_8K;
            } else if (!strcmp(transm, "TRANSMISSION_MODE_AUTO")) {
                ptr->trans = TRANSMISSION_MODE_AUTO;
            }

            if (!strcmp(gi, "GUARD_INTERVAL_1_32")) {
                ptr->gi = GUARD_INTERVAL_1_32;
            } else if (!strcmp(gi, "GUARD_INTERVAL_1_16")) {
                ptr->gi = GUARD_INTERVAL_1_16;
            } else if (!strcmp(gi, "GUARD_INTERVAL_1_8")) {
                ptr->gi = GUARD_INTERVAL_1_8;
            } else if (!strcmp(gi, "GUARD_INTERVAL_1_4")) {
                ptr->gi = GUARD_INTERVAL_1_4;
            } else {
                ptr->gi = GUARD_INTERVAL_AUTO;
            }

            if (!strcmp(tmp_lcr, "FEC_1_2")) {
                ptr->cr_lp = FEC_1_2;
            } else if (!strcmp(tmp_lcr, "FEC_2_3")) {
                ptr->cr_lp = FEC_2_3;
            } else if (!strcmp(tmp_lcr, "FEC_3_4")) {
                ptr->cr_lp = FEC_3_4;
            } else if (!strcmp(tmp_lcr, "FEC_4_5")) {
                ptr->cr_lp = FEC_4_5;
            } else if (!strcmp(tmp_lcr, "FEC_6_7")) {
                ptr->cr_lp = FEC_6_7;
            } else if (!strcmp(tmp_lcr, "FEC_8_9")) {
                ptr->cr_lp = FEC_8_9;
            } else if (!strcmp(tmp_lcr, "FEC_5_6")) {
                ptr->cr_lp = FEC_5_6;
            } else if (!strcmp(tmp_lcr, "FEC_7_8")) {
                ptr->cr_lp = FEC_7_8;
            } else if (!strcmp(tmp_lcr, "FEC_NONE")) {
                ptr->cr_lp = FEC_NONE;
            } else {
                ptr->cr_lp = FEC_AUTO;
            }


            if (!strcmp(tmp_hier, "HIERARCHY_1")) {
                ptr->hier = HIERARCHY_1;
            } else if (!strcmp(tmp_hier, "HIERARCHY_2")) {
                ptr->hier = HIERARCHY_2;
            } else if (!strcmp(tmp_hier, "HIERARCHY_4")) {
                ptr->hier = HIERARCHY_4;
            } else if (!strcmp(tmp_hier, "HIERARCHY_AUTO")) {
                ptr->hier = HIERARCHY_AUTO;
            } else {
                ptr->hier = HIERARCHY_NONE;
            }
        }

        tmp = realloc(list->channels, sizeof(dvb_channel_t) *
                      (list->NUM_CHANNELS + 1));
        if (tmp == NULL)
            break;

        list->channels = tmp;
        memcpy(&(list->channels[list->NUM_CHANNELS]), ptr, sizeof(dvb_channel_t));
        list->NUM_CHANNELS++;
        if (sizeof(dvb_channel_t) * list->NUM_CHANNELS >= 1024 * 1024) {
            mp_verbose(log, "dvbin.c, > 1MB allocated for channels struct, "
                            "dropping the rest of the file\n");
            break;
        }
    }

    fclose(f);
    if (list->NUM_CHANNELS == 0) {
        free(list->channels);
        free(list);
        return NULL;
    }

    list->current = 0;
    return list;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
// Runs charset auto-detection on the input buffer, and returns the result.
// If auto-detection fails, NULL is returned.
// If user_cp doesn't refer to any known auto-detection (for example because
// it's a real iconv codepage), user_cp is returned without even looking at
// the buf data.
// The return value may (but doesn't have to) be allocated under talloc_ctx.
const char *mp_charset_guess(void *talloc_ctx, struct mp_log *log, bstr buf,
                             const char *user_cp, int flags)
{
    if (!mp_charset_requires_guess(user_cp))
        return user_cp;

    bool use_auto = strcasecmp(user_cp, "auto") == 0;
    if (use_auto) {
#if HAVE_UCHARDET
        user_cp = "uchardet";
#elif HAVE_ENCA
        user_cp = "enca";
#else
        user_cp = "UTF-8:UTF-8-BROKEN";
#endif
    }

    bstr params[3] = {{0}};
    split_colon(user_cp, 3, params);

    bstr type = params[0];
    char lang[100];
    snprintf(lang, sizeof(lang), "%.*s", BSTR_P(params[1]));
    const char *fallback = params[2].start; // last item, already 0-terminated

    const char *res = NULL;

    if (use_auto) {
        res = ms_bom_guess(buf);
        if (res)
            type = bstr0("auto");
    }

#if HAVE_ENCA
    if (bstrcasecmp0(type, "enca") == 0)
        res = enca_guess(log, buf, lang);
#endif
#if HAVE_LIBGUESS
    if (bstrcasecmp0(type, "guess") == 0)
        res = libguess_guess(log, buf, lang);
#endif
#if HAVE_UCHARDET
    if (bstrcasecmp0(type, "uchardet") == 0)
        res = mp_uchardet(talloc_ctx, log, buf);
#endif

    if (bstrcasecmp0(type, "utf8") == 0 || bstrcasecmp0(type, "utf-8") == 0) {
        if (!fallback)
            fallback = params[1].start; // must be already 0-terminated
        int r = bstr_validate_utf8(buf);
        if (r >= 0 || (r > -8 && (flags & MP_ICONV_ALLOW_CUTOFF)))
            res = "utf-8";
    }

    if (res) {
        mp_dbg(log, "%.*s detected charset: '%s'\n", BSTR_P(type), res);
    } else {
        res = fallback;
        mp_dbg(log, "Detection with %.*s failed: fallback to %s\n",
               BSTR_P(type), res && res[0] ? res : "broken UTF-8/Latin1");
    }

    if (!res && !(flags & MP_STRICT_UTF8))
        res = "UTF-8-BROKEN";

    mp_verbose(log, "Using charset '%s'.\n", res);
    return res;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
dvb_config_t *dvb_get_config(stream_t *stream)
{
        struct mp_log *log = stream->log;
        struct mpv_global *global = stream->global;
        int i, fd, type, size;
        char filename[30], *conf_file, *name;
        dvb_channels_list *list;
        dvb_card_config_t *cards = NULL, *tmp;
        dvb_config_t *conf = NULL;


        conf = malloc(sizeof(dvb_config_t));
        if(conf == NULL)
                return NULL;

        conf->priv = NULL;
        conf->count = 0;
        conf->cards = NULL;
        for(i=0; i<MAX_CARDS; i++)
        {
                snprintf(filename, sizeof(filename), "/dev/dvb/adapter%d/frontend0", i);
                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;
                }

                type = dvb_get_tuner_type(fd, log);
                close(fd);
                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);
        conf_file = mp_find_config_file(talloc_ctx, global, "channels.conf");
        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 && (access(conf_file, F_OK | R_OK) != 0))
            conf_file = mp_find_config_file(talloc_ctx, global, "channels.conf");

        list = dvb_get_channels(log, conf_file, type);
        talloc_free(talloc_ctx);

                if(list == NULL)
                        continue;

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

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

                name = malloc(20);
                if(name==NULL)
                {
                        fprintf(stderr, "DVB_CONFIG, can't realloc 20 bytes, skipping\n");
                        continue;
                }

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

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

        return conf;
}
Ejemplo n.º 17
0
static bool subreader_autodetect(stream_t *fd, struct MPOpts *opts,
                                 struct mp_log *log, struct subreader *out)
{
    static const struct subreader sr[]=
    {
	    { sub_read_line_microdvd, NULL, "microdvd", "microdvd" },
	    { sub_read_line_subrip, NULL, "subviewer" },
	    { sub_read_line_subviewer, NULL, "subrip", "subrip" },
	    { sub_read_line_sami, NULL, "sami" },
	    { sub_read_line_vplayer, NULL, "vplayer" },
	    { sub_read_line_rt, NULL, "rt" },
	    { sub_read_line_ssa, NULL, "ssa", "ass-text" },
	    { sub_read_line_pjs, NULL, "pjs" },
	    { sub_read_line_mpsub, NULL, "mpsub" },
	    { sub_read_line_aqt, NULL, "aqt" },
	    { sub_read_line_subviewer2, NULL, "subviewer 2.0" },
	    { sub_read_line_subrip09, NULL, "subrip 0.9" },
	    { sub_read_line_jacosub, NULL, "jacosub" },
	    { sub_read_line_mpl2, NULL, "mpl2" }
    };
    const struct subreader *srp;

    int sub_format = SUB_INVALID;
    int utf16;
    int uses_time = 0;
    for (utf16 = 0; sub_format == SUB_INVALID && utf16 < 3; utf16++) {
        sub_format=sub_autodetect (fd, &uses_time, utf16);
        stream_seek(fd,0);
    }
    utf16--;

    if (sub_format==SUB_INVALID) {
        mp_verbose(log, "Could not determine file format\n");
        return false;
    }
    srp=sr+sub_format;
    mp_verbose(log, "Detected subtitle file format: %s\n", srp->name);

    *out = *srp;
    out->args = (struct readline_args) {
        .log = log,
        .utf16 = utf16,
        .opts = opts,
        .sub_slacktime = 20000, //20 sec
        .mpsub_multiplier = (uses_time ? 100.0 : 1.0),
        .uses_time = uses_time,
    };

    return true;
}

static sub_data* sub_read_file(stream_t *fd, struct subreader *srp)
{
    struct MPOpts *opts = fd->opts;
    float fps = 23.976;
    int n_max, i, j;
    subtitle *first, *sub, *return_sub, *alloced_sub = NULL;
    sub_data *subt_data;
    int sub_num = 0, sub_errs = 0;
    struct readline_args args = srp->args;

    sub_num=0;n_max=32;
    first=malloc(n_max*sizeof(subtitle));
    if (!first)
        abort();

    alloced_sub =
    sub = malloc(sizeof(subtitle));
    //This is to deal with those formats (AQT & Subrip) which define the end of a subtitle
    //as the beginning of the following
    args.previous_sub_end = 0;
    while(1){
        if(sub_num>=n_max){
            n_max+=16;
            first=realloc(first,n_max*sizeof(subtitle));
        }
	memset(sub, '\0', sizeof(subtitle));
        sub=srp->read(fd, sub, &args);
        if(!sub) break;   // EOF

	if ( sub == ERR )
	 {
	  free(first);
	  free(alloced_sub);
	  return NULL;
	 }
        // Apply any post processing that needs recoding first
        if ((sub!=ERR) && srp->post) srp->post(sub);
	if(!sub_num || (first[sub_num - 1].start <= sub->start)){
	    first[sub_num].start = sub->start;
  	    first[sub_num].end   = sub->end;
	    first[sub_num].lines = sub->lines;
	    first[sub_num].alignment = sub->alignment;
  	    for(i = 0; i < sub->lines; ++i){
		first[sub_num].text[i] = sub->text[i];
  	    }
	    if (args.previous_sub_end){
  		first[sub_num - 1].end = args.previous_sub_end;
    		args.previous_sub_end = 0;
	    }
	} else {
	    for(j = sub_num - 1; j >= 0; --j){
    		first[j + 1].start = first[j].start;
    		first[j + 1].end   = first[j].end;
		first[j + 1].lines = first[j].lines;
		first[j + 1].alignment = first[j].alignment;
    		for(i = 0; i < first[j].lines; ++i){
      		    first[j + 1].text[i] = first[j].text[i];
		}
		if(!j || (first[j - 1].start <= sub->start)){
	    	    first[j].start = sub->start;
	    	    first[j].end   = sub->end;
	    	    first[j].lines = sub->lines;
	    	    first[j].alignment = sub->alignment;
	    	    for(i = 0; i < SUB_MAX_TEXT; ++i){
			first[j].text[i] = sub->text[i];
		    }
		    if (args.previous_sub_end){
			first[j].end = first[j - 1].end;
			first[j - 1].end = args.previous_sub_end;
			args.previous_sub_end = 0;
		    }
		    break;
    		}
	    }
	}
        if(sub==ERR) ++sub_errs; else ++sub_num; // Error vs. Valid
    }

    free(alloced_sub);

//    printf ("Subtitle format %s time.\n", uses_time?"uses":"doesn't use");
    MP_VERBOSE(&srp->args, "Read %i subtitles, %i bad line(s).\n",
           sub_num, sub_errs);

    if(sub_num<=0){
	free(first);
	return NULL;
    }

    adjust_subs_time(srp, first, 6.0, fps, opts->sub_fps, 1, sub_num, args.uses_time);/*~6 secs AST*/
    return_sub = first;

    if (return_sub == NULL) return NULL;
    subt_data = talloc_zero(NULL, sub_data);
    subt_data->codec = srp->codec_name ? srp->codec_name : "text";
    subt_data->sub_uses_time = args.uses_time;
    subt_data->sub_num = sub_num;
    subt_data->sub_errs = sub_errs;
    subt_data->subtitles = return_sub;
    subt_data->fallback_fps = fps;
    return subt_data;
}

static void subdata_free(sub_data *subd)
{
    int i, j;
    for (i = 0; i < subd->sub_num; i++)
        for (j = 0; j < subd->subtitles[i].lines; j++)
            free( subd->subtitles[i].text[j] );
    free( subd->subtitles );
    talloc_free(subd);
}
Ejemplo n.º 18
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

bool mp_might_be_subtitle_file(const char *filename)
{
    return test_ext(get_ext(bstr0(filename))) == STREAM_SUB;
}

static int compare_sub_filename(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    return strcoll(s1->fname, s2->fname);
}

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && mp_isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

static void append_dir_subtitles(struct mpv_global *global,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    void *tmpmem = talloc_new(NULL);
    struct MPOpts *opts = global->opts;
    struct mp_log *log = mp_log_new(tmpmem, global->log, "find_files");

    if (mp_is_url(bstr0(fname)))
        goto out;

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_verbose(log, "Loading external files in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // check what it is (most likely)
        int type = test_ext(tmp_fname_ext);
        char **langs = NULL;
        int fuzz = -1;
        switch (type) {
        case STREAM_SUB:
            langs = opts->sub_lang;
            fuzz = opts->sub_auto;
            break;
        case STREAM_AUDIO:
            langs = opts->audio_lang;
            fuzz = opts->audiofile_auto;
            break;
        }

        if (fuzz < 0)
            goto next_sub;

        // we have a (likely) subtitle file
        int prio = 0;
        char *found_lang = NULL;
        if (langs) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; langs[n]; n++) {
                        if (bstr_startswith0(lang, langs[n])) {
                            prio = 4; // matches the movie name + lang extension
                            found_lang = langs[n];
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0 && fuzz >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && fuzz >= 2) {
                prio = 1;
            }
        }

        mp_dbg(log, "Potential external file: \"%s\"  Priority: %d\n",
               de->d_name, prio);

        if (prio) {
            prio += prio;
            char *subpath = mp_path_join(*slist, path, dename);
            if (mp_path_exists(subpath)) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                // annoying and redundant
                if (strncmp(subpath, "./", 2) == 0)
                    subpath += 2;

                sub->type     = type;
                sub->priority = prio;
                sub->fname    = subpath;
                sub->lang     = found_lang;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

static bool case_endswith(const char *s, const char *end)
{
    size_t len = strlen(s);
    size_t elen = strlen(end);
    return len >= elen && strcasecmp(s + len - elen, end) == 0;
}

// Drop .sub file if .idx file exists.
// Assumes slist is sorted by compare_sub_filename.
static void filter_subidx(struct subfn **slist, int *nsub)
{
    const char *prev = NULL;
    for (int n = 0; n < *nsub; n++) {
        const char *fname = (*slist)[n].fname;
        if (case_endswith(fname, ".idx")) {
            prev = fname;
        } else if (case_endswith(fname, ".sub")) {
            if (prev && strncmp(prev, fname, strlen(fname) - 4) == 0)
                (*slist)[n].priority = -1;
        }
    }
    for (int n = *nsub - 1; n >= 0; n--) {
        if ((*slist)[n].priority < 0)
            MP_TARRAY_REMOVE_AT(*slist, *nsub, n);
    }
}

// Return a list of subtitles and audio files found, sorted by priority.
// Last element is terminated with a fname==NULL entry.
struct subfn *find_external_files(struct mpv_global *global, const char *fname)
{
    struct MPOpts *opts = global->opts;
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(global, &slist, &n, mp_dirname(fname), fname, 0);

    if (opts->sub_auto >= 0) {
        // Load subtitles in dirs specified by sub-paths option
        if (opts->sub_paths) {
            for (int i = 0; opts->sub_paths[i]; i++) {
                char *path = mp_path_join(slist, mp_dirname(fname),
                                        bstr0(opts->sub_paths[i]));
                append_dir_subtitles(global, &slist, &n, bstr0(path), fname, 0);
            }
        }

        // Load subtitles in ~/.mpv/sub limiting sub fuzziness
        char *mp_subdir = mp_find_config_file(NULL, global, "sub/");
        if (mp_subdir)
            append_dir_subtitles(global, &slist, &n, bstr0(mp_subdir), fname, 1);
        talloc_free(mp_subdir);
    }

    // Sort by name for filter_subidx()
    qsort(slist, n, sizeof(*slist), compare_sub_filename);

    filter_subidx(&slist, &n);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    struct subfn z = {0};
    MP_TARRAY_APPEND(NULL, slist, n, z);

    return slist;
}
Ejemplo n.º 19
0
static mf_t *open_mf_pattern(void *talloc_ctx, struct mp_log *log, char *filename)
{
    int error_count = 0;
    int count = 0;

    mf_t *mf = talloc_zero(talloc_ctx, mf_t);
    mf->log = log;

    if (filename[0] == '@') {
        FILE *lst_f = fopen(filename + 1, "r");
        if (lst_f) {
            char *fname = talloc_size(mf, 512);
            while (fgets(fname, 512, lst_f)) {
                /* remove spaces from end of fname */
                char *t = fname + strlen(fname) - 1;
                while (t > fname && mp_isspace(*t))
                    *(t--) = 0;
                if (!mp_path_exists(fname)) {
                    mp_verbose(log, "file not found: '%s'\n", fname);
                } else {
                    mf_add(mf, fname);
                }
            }
            fclose(lst_f);

            mp_info(log, "number of files: %d\n", mf->nr_of_files);
            goto exit_mf;
        }
        mp_info(log, "%s is not indirect filelist\n", filename + 1);
    }

    if (strchr(filename, ',')) {
        mp_info(log, "filelist: %s\n", filename);
        bstr bfilename = bstr0(filename);

        while (bfilename.len) {
            bstr bfname;
            bstr_split_tok(bfilename, ",", &bfname, &bfilename);
            char *fname2 = bstrdup0(mf, bfname);

            if (!mp_path_exists(fname2))
                mp_verbose(log, "file not found: '%s'\n", fname2);
            else {
                mf_add(mf, fname2);
            }
            talloc_free(fname2);
        }
        mp_info(log, "number of files: %d\n", mf->nr_of_files);

        goto exit_mf;
    }

    char *fname = talloc_size(mf, strlen(filename) + 32);

    if (!strchr(filename, '%')) {
        strcpy(fname, filename);
        if (!strchr(filename, '*'))
            strcat(fname, "*");

        mp_info(log, "search expr: %s\n", fname);

        glob_t gg;
        if (glob(fname, 0, NULL, &gg)) {
            talloc_free(mf);
            return NULL;
        }

        for (int i = 0; i < gg.gl_pathc; i++) {
            if (mp_path_isdir(gg.gl_pathv[i]))
                continue;
            mf_add(mf, gg.gl_pathv[i]);
        }
        mp_info(log, "number of files: %d\n", mf->nr_of_files);
        globfree(&gg);
        goto exit_mf;
    }

    mp_info(log, "search expr: %s\n", filename);

    while (error_count < 5) {
        sprintf(fname, filename, count++);
        if (!mp_path_exists(fname)) {
            error_count++;
            mp_verbose(log, "file not found: '%s'\n", fname);
        } else {
            mf_add(mf, fname);
        }
    }

    mp_info(log, "number of files: %d\n", mf->nr_of_files);

exit_mf:
    return mf;
}