LINUX.ORG.RU

Сообщения cdslow

 

fictionup 0.2.1

Выложил у себя на сайте обновлённую версию fictionup, которая должна собираться на Gentoo.

В самой программе изменений нет, только в CMakeLists.txt добавлена проверка на патченную версию ZLib.

 , ,

cdslow
()

Transmission patch

Я сделал патч для transmission-2.94, который добавляет к анонсам поле «ip=» и дополнительный заголовок «X-Forwarded-For» с адресом шлюза. Это всё нужно для удобной работы через прокси.

Патч: https://yadi.sk/d/4e2Vp7Xh3XqTmD

Исходники transmission лежат на github, а я там не зарегистрирован, и регистрироваться особого желания нет.

Если есть желающие отправить им пул-реквест - милости прошу.

 , , ,

cdslow
()

Установить переменную окружения для всех графических приложений в Fedora

Обновил я у себя Fedora, и испортились у меня после этого шрифты. Поискал в Интернете в чём дело и выяснил, что во Freetype поменялся алгоритм BCI по умолчанию, и вернуть всё обратно можно установив переменную окружения FREETYPE_PROPERTIES со значением truetype:interpreter-version=35.

Хорошо, создаю файл /etc/profile.d/fonts.sh, пишу в нём:

export FREETYPE_PROPERTIES='truetype:interpreter-version=35'

Перезапускаю сеанс — ура, старые шрифты вернулись, глазкам полегчало.

Но. Запускаю с рабочего стола документ LibreOffice, и опаньки, снова кривые шрифты.

Начинаю разбираться в чём дело. Документ с рабочего стола запускается через systemd dbus activation, а оно на profile.d плевать хотело. Ладно, создаю файл /etc/systemd/system.conf.d/env.conf, пишу в нём:

[Manager]
DefaultEnvironment='FREETYPE_PROPERTIES=truetype:interpreter-version=35'

Перезагружаю систему — да, теперь шрифты нормальные и в LibreOffice.

Внимание вопрос: есть в Fedora какое-то одно место, где можно прописать переменную окружения для всех графических (или вообще всех) приложений, не повторяя одно и то же несколько раз?

 , , , ,

cdslow
()

Новая версия программы для слайдшоу c эффектами переходов — sleid0r 0.3

Готова новая версия программы sleid0r. Добавлен новый режим сортировки изображений — перемешивать каталоги, а также управляющие клавиши: пауза, вперёд и назад.

Сайт

Исходники

Пакеты

 , ,

cdslow
()

Что повесить на пробел — паузу или листание?

Решил я добавить в свою программу для слайдшоу (sleid0r) управляющие клавиши для листания вперёд/назад и для установки паузы. И теперь в раздумьях — какую из этих функций повесить на клавишу пробел?

С одной стороны, во многих программах пробел используется для перехода вперёд, с другой, во многих видеоплеерах он используется как клавиша паузы.

А какое поведение вы интуитивно ожидаете от пробела при показе слайдшоу?

 ,

cdslow
()

PgcDemux для Linux

Я собрал консольную версию PgcDemux. Может, кому-нибудь пригодится.

Исходники: http://cdslow.org.ru/files/cpgcdemux/cpgcdemux-0.1.tar.gz

Пакеты: http://download.opensuse.org/repositories/home:/cdslow:/cpgcdemux/

 , ifo, m2v,

cdslow
()

[vala][srt2tmx] Покритикуйте код

Осваиваю vala. Без практической задачи мне программировать не интересно, поэтому реализовал то, в чём у меня сейчас была потребность.

Программа читает два набора .srt файлов на двух языках, и на основе сопоставления временных меток создаёт файл памяти перевода (translation memory) в формате tmx.

Программа работает, своё дело сделала, но мне интересно, что можно было написать проще/эффективнее/понятнее (например, мне не нравится, как организован двумерный динамический массив для имён файлов).

Много кода:

struct TextEvent
    {
    double begin;
    double end;
    string text;
    }

struct TextPair
    {
    string orig;
    string trans;
    }

struct StringArray
    {
    string[] sa;
    }

int main(string[] args)
    {
    string[] lang_codes={}; /* Languages */
    StringArray[] lang_data={}; /* Source file names */
    string out_file=null; /* Output file name */

    int file_i=0; /* Source file number */

    /* Process command line arguments */
    for(int i=1; i < args.length; ++i)
        {
        if(args[i].has_prefix("-"))
            {
            /* It's an option */
            string opt=args[i].substring(1);
            if("o" == opt)
                {
                /* Output file name */
                ++i;
                if(i < args.length)
                    out_file=args[i];
                }
            else if(2 == opt.length)
                {
                /* Language code */
                lang_codes+=opt.up();
                file_i=0;
                }
            else
                {
                /* Some shit */
                stderr.printf("Invalid option: %s\n", args[i]);
                return 1;
                }
            }
        else
            {
            /* It's a file name */
            if(0 == lang_codes.length)
                {
                /* Language code must go first */
                stderr.printf("Language undefined!\n");
                return 1;
                }

            if(lang_data.length <= file_i)
                {
                /* Allocate new set of files */
                lang_data.resize(file_i + 1);
                lang_data[file_i].sa={};
                }

            if(lang_data[file_i].sa.length < lang_codes.length)
                /* Allocate space for file name */
                lang_data[file_i].sa.resize(lang_codes.length);

            /* Store file name */
            lang_data[file_i].sa[lang_codes.length-1]=args[i];
            ++file_i;
            }
        }

    /* Print source file names */
    for(int lang_i=0; lang_i < lang_codes.length; ++lang_i)
        {
        stdout.printf("%s files:\n", lang_codes[lang_i]);
        foreach(var ld in lang_data)
            {
            if(null == ld.sa[lang_i])
                {
                stderr.printf("File lists mismatch!\n");
                return 1;
                }
            stdout.printf("  %s\n", ld.sa[lang_i]);
            }
        }

    if(lang_codes.length != 2)
        {
        stderr.printf("There must be 2 input languages!\n");
        return 1;
        }

    if(null == out_file)
        {
        stderr.printf("Missing output file name!\n");
        return 1;
        }

    TextPair[] pairs={}; /* Translations */

    /* Process file sets */
    foreach(var ld in lang_data)
        {
        if(null == ld.sa[0] || null == ld.sa[1])
            {
            stderr.printf("File lists mismatch!\n");
            return 1;
            }

        stdout.printf("Processing:\n  %s\n  %s\n", ld.sa[0], ld.sa[1]);

        try
            {
            /* Read, parse and match */
            match_events(ref pairs, ld.sa);
            }
        catch(FileError e)
            {
            stderr.printf("%s\n", e.message);
            return 1;
            }

        }

    /* Write XML */
    stdout.printf("Writing: %s\n", out_file);
    write_pairs(out_file, pairs, lang_codes);

    return 0;
    }

/* Process file set */
void match_events(ref TextPair[] pairs, string[] file_set) throws FileError
    {
    TextEvent[] orig, trans; /* Parsed srt data */
    int i_trans=0, i_orig=0; /* String numbers */
    double o_begin, o_end, o_mid; /* Original time interval */
    double t_begin, t_end, t_mid; /* Translated time interval */

    /* Read and parse files */
    orig=parse_srt(file_set[0]);
    trans=parse_srt(file_set[1]);

    /* Process text events */
    while(i_orig < orig.length && i_trans < trans.length)
        {
        /* Calculate original time interval */
        o_begin=orig[i_orig].begin;
        o_end=orig[i_orig].end;
        o_mid=(o_begin + o_end) / 2.0;
        /* Calculate transalted time interval */
        t_begin=trans[i_trans].begin;
        t_end=trans[i_trans].end;
        t_mid=(t_begin + t_end) / 2.0;
        /* Test for interval match */
        if(t_mid > o_begin && t_mid < o_end || o_mid > t_begin && o_mid < t_end)
            {
            /* Store matched text */
            push_pair(ref pairs, orig[i_orig].text, trans[i_trans].text);
            ++i_trans;
            ++i_orig;
            /* Concatenate overlapping events */
            do
                {
                while(i_trans < trans.length)
                    {
                    t_mid=(trans[i_trans].begin + trans[i_trans].end) / 2.0;
                    if(t_mid < o_begin || t_mid > o_end)
                        break;
                    pairs[pairs.length-1].trans+=" " + trans[i_trans].text;
                    t_end=trans[i_trans].end;
                    ++i_trans;
                    }
                while(i_orig < orig.length)
                    {
                    o_mid=(orig[i_orig].begin + orig[i_orig].end) / 2.0;
                    if(o_mid < t_begin || o_mid > t_end)
                        break;
                    pairs[pairs.length-1].orig+=" " + orig[i_orig].text;
                    o_end=orig[i_orig].end;
                    ++i_orig;
                    }
                }
            while(t_mid > o_begin && t_mid < o_end && i_trans < trans.length);
            }
        else
            {
            /* No matching event */
            if(o_mid < t_mid)
                {
                /* Skip original */
                /*push_pair(ref pairs, orig[i_orig].text, "");*/
                ++i_orig;
                }
            else
                {
                /* Skip translated */
                /*push_pair(ref pairs, "", trans[i_trans].text);*/
                ++i_trans;
                }
            }
        }
    }

/* Append text pair to array */
void push_pair(ref TextPair[] pairs, string t1, string t2)
    {
    pairs.resize(pairs.length+1);
    pairs[pairs.length-1].orig=t1;
    pairs[pairs.length-1].trans=t2;
    }

/* Read and parse srt file */
TextEvent[] parse_srt(string file_name) throws FileError 
    {
    TextEvent[] parsed={};
    string file_text;

    /* Read file */
    FileUtils.get_contents(file_name, out file_text, null);

    /* Parse text */
    foreach(var srt_group in file_text.replace("\r", "").split("\n\n"))
        {
        var srt_part=srt_group.strip().split("\n", 3);
        if(srt_part.length<3)
            break;
        var time_text=srt_part[1].split("-->", 2);
        parsed.resize(parsed.length+1);
        parsed[parsed.length-1].begin=parse_time_value(time_text[0]);
        parsed[parsed.length-1].end=parse_time_value(time_text[1]);
        parsed[parsed.length-1].text=srt_part[2].replace("\n", " ");
        }

    return parsed;
    }

/* Convert srt time to double */
double parse_time_value(string time_text)
    {
    double time_value;

    var time_parts=time_text.strip().replace(",", ".").split(":", 3);
    time_value=double.parse(time_parts[2]);
    time_value+=double.parse(time_parts[1])*60.0;
    time_value+=double.parse(time_parts[0])*3600.0;

    return time_value;
    }

/* Write XML file */
void write_pairs(string file_name, TextPair[] pairs, string[] lang_codes)
    {
    var xml=new Xml.TextWriter.filename(file_name);

    xml.set_indent(true);
    xml.start_document();
    xml.start_element("tmx");
        xml.write_attribute("version", "1.4");
        xml.write_attribute("xmlns", "http://www.localization.org/tmx14");
        xml.start_element("header");
            xml.write_attribute("creationtool", "srt2tmx");
            xml.write_attribute("creationtoolversion", "0.1");
            xml.write_attribute("datatype", "PlainText");
            xml.write_attribute("segtype", "sentence");
            xml.write_attribute("adminlang", "en-us");
            xml.write_attribute("srclang", lang_codes[0]);
            xml.write_attribute("o-tmf", "srt2tmx");
        xml.end_element();
        xml.start_element("body");
    foreach(var p in pairs)
        {
            xml.start_element("tu");
                xml.start_element("tuv");
                    xml.write_attribute("xml:lang", lang_codes[0]);
                    xml.write_element("seg", p.orig);
                xml.end_element();
                xml.start_element("tuv");
                    xml.write_attribute("xml:lang", lang_codes[1]);
                    xml.write_element("seg", p.trans);
                xml.end_element();
            xml.end_element();
        }
        xml.end_element();
    xml.end_element();
    xml.end_document();
    xml.flush();
    }

 ,

cdslow
()

Видеофильтры

Придумал я несколько алгоритмов для фильтрации видео. И начал я их реализовывать для программы transcode. Но transcode скоропостижно скончалась. Тогда я решил переписать их под mencoder. Но API у mencoder мало того, что запутанный, так как завязан на mplayer с его оптимизациями, так ещё и не позволяет свободно манипулировать удалением/добавлением/перестановкой кадров. В общем, написал я собственный вариант API для видеофильтрации. И реализовал фильтры на нём.

Основная идея в том, что вся внутренняя обработка ведётся строго в одном формате цветности - yuv444 и фильтры могут буферизировать у себя любое количество кадров и выдавать их в любой последовательности.

Исходный код: video3x-0.1.tar.gz

Исполняемые файлы для Linux: video3x-0.1-linux.tar.gz

Исполняемые файлы для Windows: video3x-0.1-windows.zip

Опции командной строки (по английски): video3x-0.1-help.txt

Лицензия - LGPL 3+.

cdslow
()

[ffmpeg] Замена ключа -s на -video_size в ffplay

API в ffmpeg ломают постоянно, к этому все давно привыкли.

А теперь сломали командную строку очень оригинальным образом. Итак, в fedora-16 ffplay не проигрывает raw-видео с ключём -s для указания размера кадра, вместо него теперь нужно использовать ключ -video_size. Всё бы ничего, только про этот ключ в справке ffplay ни слова.

Собственно вопрос: как в скрипте определить, какой ключ использовать для проигрывания raw-видео?

Может быть, кто-нибудь знает, с какой именно версии ffplay изменился ключ, чтобы сделать проверку по версии?

 

cdslow
()

[C] Выбор структуры данных для видеофильтров

Пишу фреймворк для фильтрации видео. Не могу окончательно решить, какую структуру данных использовать для хранения обрабатываемых кадров.

Вариант 1:

typedef struct image_s
    {
    int w;
    int h;
    int sz_yy;
    int sz_buf;
    uint8_t *buf;
    uint8_t *yy;
    uint8_t *cb;
    uint8_t *cr;
    } image_t;

Вариант 2:

typedef struct pixel_s
    {
    uint8_t yy;
    uint8_t cb;
    uint8_t cr;
    } pixel_t;

typedef struct image_s
    {
    int w;
    int h;
    int px_count;
    int px_sz;
    pixel_t *px;
    } image_t;

Первый вариант удобнее импортировать/экспортировать из планарных форматов (yv12, yuv420p) и обрабатывать покомпонентными фильтрами.

Второй вариант удобнее обрабатывать попиксельными фильтрами, и использовать при этом код типа такого:

out->px[xy]=in->px[xy];
вместо такого:
out->yy[xy]=in->yy[xy];
out->cb[xy]=in->cb[xy];
out->cr[xy]=in->cr[xy];

Есть какие-нибудь аргументы, чтобы остановиться на одном из вариантов?

 

cdslow
()

RSS подписка на новые темы