Пример #1
0
void print_libav_versions(struct mp_log *log, int v)
{
    const struct lib libs[] = {
        {"libavutil",     LIBAVUTIL_VERSION_INT,     avutil_version()},
        {"libavcodec",    LIBAVCODEC_VERSION_INT,    avcodec_version()},
        {"libavformat",   LIBAVFORMAT_VERSION_INT,   avformat_version()},
        {"libswscale",    LIBSWSCALE_VERSION_INT,    swscale_version()},
#if HAVE_LIBAVFILTER
        {"libavfilter",   LIBAVFILTER_VERSION_INT,   avfilter_version()},
#endif
#if HAVE_LIBAVRESAMPLE
        {"libavresample", LIBAVRESAMPLE_VERSION_INT, avresample_version()},
#endif
#if HAVE_LIBSWRESAMPLE
        {"libswresample", LIBSWRESAMPLE_VERSION_INT, swresample_version()},
#endif
    };

    mp_msg(log, v, "%s library versions:\n", LIB_PREFIX);

    bool mismatch = false;
    bool broken = false;
    for (int n = 0; n < MP_ARRAY_SIZE(libs); n++) {
        const struct lib *l = &libs[n];
        mp_msg(log, v, "   %-15s %d.%d.%d", l->name, V(l->buildv));
        if (l->buildv != l->runv) {
            mp_msg(log, v, " (runtime %d.%d.%d)", V(l->runv));
            mismatch = true;
            broken |= ((l->buildv & 255) >= 100) != ((l->runv & 255) >= 100);
        }
        mp_msg(log, v, "\n");
    }
    // This just won't work. It's 100% broken.
    if (broken) {
        mp_fatal(log, "mpv was compiled and linked against a mixture of Libav "
                 "and FFmpeg versions. This won't work and will most likely "
                 "crash at some point. Exiting.\n");
        exit(42);
    }
    // We don't "really" support mismatched libraries, but if you like to
    // suffer, you're free to enjoy the terrible aspects of dynamic linking.
    // In particular, we don't use all these crazy accessors ffmpeg wants us
    // to use in order to be ABI compatible after Libav merges - because that
    // would make our code incompatible to Libav. It's madness.
    if (mismatch) {
        mp_warn(log, "Warning: mpv was compiled against a different version of "
                "%s than the shared\nlibrary it is linked against. This can "
                "expose subtle ABI compatibility issues\nand can lead to "
                "misbehavior and crashes.\n", LIB_PREFIX);
    }
}
Пример #2
0
static int validate_device_opt(struct mp_log *log, const m_option_t *opt,
                               struct bstr name, struct bstr param)
{
    if (bstr_equals0(param, "help")) {
        if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_TRUE) {
            mp_fatal(log, "Device listing not supported.\n");
            return M_OPT_EXIT;
        }
        const char *list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
        mp_info(log, "OpenAL devices:\n");
        while (list && *list) {
            mp_info(log, "  '%s'\n", list);
            list = list + strlen(list) + 1;
        }
        return M_OPT_EXIT - 1;
    }
    return 0;
}
Пример #3
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;
}
Пример #4
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;
}