Эмуляция > Эмуляторы консолей 1-4 поколений
HD-видео 8-битных игр
(1/2) > >>
Gilroy:
Наткнулся на канал TopRetroGames на ютубе, где выложены прохождения 8-битных игр в HD (720p).

Непосредственно автору этих видео я писать не стал, так как на комментарии он вообще не отвечает. На канале размещена ссылка на Emu-Land, поэтому спрошу здесь.

Как можно добиться такого же качества? Какой эмулятор для этого нужен, какая монтажка, какие опции надо выставлять?
Valet2:
Вот как по мне, вся пикселявость там на месте - никакого необычного качества.

А отсутствие смазанности - из-за того, что автор не стал записывать и выкладывать видео разрешения 320x240, как всякие дебилы, а увеличил его до HD со ступенчатой интерполяцией - все несовские пиксели остались квадратными, но сделались крупными.

Вот, например, так выглядит кадр в замечательном клиппе Move Your Feet группы Junior and Senior:



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



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



Клип можете скачать у меня.
Gilroy:
Valet2, большое Вам спасибо за развёрнутый ответ.


--- Цитата: Valet2 от 26 Февраль 2013, 12:14:50 ---Вот как по мне, вся пикселявость там на месте - никакого необычного качества.
--- Конец цитаты ---

Да, никакого необычного качества. Но всё равно в HD смотрится лучше.


--- Цитата: Valet2 от 26 Февраль 2013, 12:14:50 ---А отсутствие смазанности - из-за того, что автор не стал записывать и выкладывать видео разрешения 320x240, как всякие дебилы, а увеличил его до HD со ступенчатой интерполяцией - все несовские пиксели остались квадратными, но сделались крупными.
--- Конец цитаты ---

Довелось мне уже столкнуться с этой смазанностью, когда я пытался в Premiere увеличить масштаб NES’овского видео. Смотрелось ужасно.

Как можно применить эту ступенчатую интерполяцию? Это делается на стадии захвата или уже потом?
Valet2:
я не знаю, как в премьере, но в Вегасе это делается в настройках проекта
Gilroy:
Буду пробовать.
Gilroy:
Итак, установил я Vegas Pro 10.

Видео пишу в FCEUX 2.1.5. Получаю файл с такими свойствами:

Video: 256x224 (1.14:1), 60.100 fps,  ~82713 kbps avg, 24.00 bit/pixel
Audio: 44.100 kHz, Microsoft PCM, 1 ch, ~705.60 kbps avg

1. Как растянуть это видео на весь экран, чтобы не было полос вверху и внизу?
2. Где находится та заветная опция, которая включает ступенчатую интерполяцию?
Partsigah:
Как сделать ступенчатую интерполяцию в VirtualDub?
Ещё вопрос, можно-ли в Нестопии сделать видео 640х480 (кратно 320-ти) не растягивая окно вручную?
Получилось:
Эмулятор: Nestopia 1.41 - 640x480
Запись через HyperCam 2: x264wfv (Fast decode / Still Image / Zero Latency / FVW Four CC: avc1 / Virtual Dub hack)
Далее Virtual Dub: Filters - Resize - Nearest neighbor - 200% / Compression - x264wfv
Главной проблемой было сделать захват, т.к. h264 постоянно рассинхронивал аудио, то опаздывая, то опережая.
Gilroy:
Partsigah, спасибо за разъяснение!

А что если опустить этап с HyperCam’ом, а записывать напрямую через эмулятор? И затем уже выставлять в VirtualDub’е увеличение, скажем, на 500 %. Получится разрешение 1280×1120.

Кстати, откуда у всех берётся разрешение 320×240? Вот цитата из английской Википедии:


--- Цитата ---The standard display resolution of the NES is 256 horizontal pixels by 240 vertical pixels. Typically, games designed for NTSC-based systems had an effective resolution of only 256 by 224 pixels, as the top and bottom 8 scanlines are not visible on most television sets.
--- Конец цитаты ---

У меня тоже пишет 256×224. Разве так и не должно быть?
Partsigah:

--- Цитата: Gilroy от 03 Март 2013, 14:45:31 ---А что если опустить этап с HyperCam’ом, а записывать напрямую через эмулятор? И затем уже выставлять в VirtualDub’е увеличение, скажем, на 500 %. Получится разрешение 1280×1120.

--- Конец цитаты ---
Смотря какой эмуль, попробуй так сделать на fceux и залить результат на ю-туб, может будет тоже самое HD.

--- Цитата: Gilroy от 03 Март 2013, 14:45:31 ---Кстати, откуда у всех берётся разрешение 320×240? Вот цитата из английской Википедии:

У меня тоже пишет 256×224. Разве так и не должно быть?

--- Конец цитаты ---
Так это комповское разрешение, даже TV-aspect не даёт такое. Я так понял, оно для удобства заливки на ю-туб в HD.
EdHell:
Хочешь максимум качества - захватывай уже в высоком разрешении, потом только кропай.
feos:
Система для взрослых дядь такова:

1. Записываем AVI прямо с эмулятора, в родном разрешении, НО с использованием lossless кодека. Варианты:

CamStudio lossless codec
http://sourceforge.net/projects/camstudio/files/legacy/CamStudioCodec-1.4-w32.zip/download
(Для установки кликаем ПКМ по camcodec.inf и выбираем Установить)

Lagarith
http://lags.leetcode.net/codec.html

2. Пoлученный файл руками тащим в Virtual Dub и обрабатываем.

Video - Filters - Add - resize - Filter mode - Nearest neigbour. New size - Relative - 400
* Можно руками вписать разрешение 960x720, тогда будет и 4:3, и HD.
Video - Frame Rate - Convert to fps - 25
Video -> Compression -> Выбираем x265vfw (http://sourceforge.net/projects/x264vfw/files/) и жмем кнопку Configure
 
Preset -> Ultrafast
Tuning -> Animation
Rate control -> Single pass - ratefactor-based
Ratefactor ставите на 10.
Обязательно ставите галку Zero latency!

File -> Save as AVI

Вкатаракте: http://vk.com/page-53076_31720814
На инглише: http://tasvideos.org/EncodingGuide/CustomEncoding.html
Valet2:
Кстати, ютуб нормально воспринимает и 30 fps.

Lagarith рулит!
feos:
Ютуб нормfльно воспринимает и когда ты срезаешь 60-кадровое мигание до 30-кадрового. Мигания просто больше нет, но ютуб-то да, нормально воспринимает. Срезая до 25 еще есть шанс увидеть его. Хотя взрослые дяди юзают deblink функцию, основанную на создании маски мигающего объекта и смешивании только его между кадров.


--- Код: (AviSynth) ---# nanogyth's deblink.
function ng_deblink(clip clp,
\ float "ratio",
\ int "level",
\ clip "blinkmask"
\){
#Version 10 2012.04.22

    blink = default(blinkmask, clp.ng_blinkmask())

    ratio = default(ratio, 2.0 /3)
    assert(ratio >= 0.0 && 1.0 >= ratio,
    \      "[ng_deblink] 1.0 >= ratio >= 0.0, it was " + string(ratio))

    level = default(level, round(ratio * 257))
    assert(level >= 0 && 257 >= level,
    \      "[ng_deblink] 257 >= level >= 0, it was " + string(level))

    m01=mt_logic(blink.SelectEvery(4,0),
\                blink.SelectEvery(4,1),
\                mode="or").ConvertToRGB32()
    m23=mt_logic(blink.SelectEvery(4,2),
\                blink.SelectEvery(4,3),
\                mode="or").ConvertToRGB32()

    f0=Layer(clp.SelectEvery(4,0),
\            clp.SelectEvery(4,1).Mask(m01),
\            level=level)
    f1=Layer(clp.SelectEvery(4,1),
\            clp.SelectEvery(4,0).Mask(m01),
\            level=level)
    f2=Layer(clp.SelectEvery(4,2),
\            clp.SelectEvery(4,3).Mask(m23),
\            level=(257-level) )
    f3=Layer(clp.SelectEvery(4,3),
\            clp.SelectEvery(4,2).Mask(m23),
\            level=(257-level) )

    Interleave(f0,f1,f2,f3)
}

function ng_blinkmask(clip clp,
\ bool "TEST",
\ bool "STABILIZE",
\ bool "SHARP",
\ bool "HYSTER",
\ int "inpand",
\ int "expand",
\ int "ml"
\){
#Version 10 2012.04.22

#BLINK
# Blinking is a block that alternates on/off each frame
# SelectEven would only see either the on or the off

#FLASH
# Flashing is a block that is only on for a single frame
# SelectEven might miss the flash

#SHAKE
# Shaking is a block that moves back/forth each frame
# SelectEven would only see one position

# The goal of this function is to make a blink mask for use with
# ng_deblink. For overly complicated scenes where a clean blinkmask
# can't be found, just use TASBlend. Uniform softness looks better
# than sharp artifacts.

# This function calculates flash and shake info for the test script,
# but those effects should be handled in different ways.
# Flash - choose frames to make sure the flash is in your final clip.
# Shake - SelectEvery(4,0,2,1,3) or SelectEvery(4,1,0,2,3)
# SelectEvery doesn't generally work because it messes with the fluidity
# of motion. But that won't be noticable on a shaking screen.
# Be careful if 2 frame blinking is present, as the selectevery can turn
# it into 1 frame blinking.

    TEST      = default(     TEST, false)
    STABILIZE = default(STABILIZE, true)
    SHARP     = default(    SHARP, true)
    HYSTER    = default(   HYSTER, false)
    inpand    = default(   inpand, 1)
    expand    = default(   expand, 1)
    ml        = default(       ml, 128)

# The functions used to make the masks work in the YV12 colorspace. Once
# the masks are created they can be used in the RGB32 colorspace direcly
    src=clp.ConvertToYV12()

# Blinking is located by looking for blocks that don't exist in
# consecutive frames. The motion vector will match blocks that exist in
# both frames. The blocks that aren't in both will end up with huge
# values that are picked out by the motion mask.
    super = MSuper(src, pel=1)
    fvec  = MAnalyse(super, isb=false, blksize=4)
    bvec  = MAnalyse(super, isb=true , blksize=4)
    fmask = Mmask(src, fvec, kind=1, ml=ml).mt_binarize()
    bmask = Mmask(src, bvec, kind=1, ml=ml).mt_binarize()
    blink = mt_logic(fmask, bmask, mode="and")

# Blinking usually occurs against a stable background. This is found
# by looking at blocks 2 frames apart. This distinguishes a blink from
# blocks that are just changing every frame.
    ee_src   = src.SelectEven()
    ee_super = MSuper(ee_src, pel=1)
    ee_fvec  = MAnalyse(ee_super, isb=false, blksize=4)
    ee_bvec  = MAnalyse(ee_super, isb=true , blksize=4)
    ee_fmask = Mmask(ee_src, ee_fvec, kind=1, ml=ml).mt_binarize()
    ee_bmask = Mmask(ee_src, ee_bvec, kind=1, ml=ml).mt_binarize()

    oo_src   = src.SelectOdd()
    oo_super = MSuper(oo_src, pel=1)
    oo_fvec  = MAnalyse(oo_super, isb=false, blksize=4)
    oo_bvec  = MAnalyse(oo_super, isb=true , blksize=4)
    oo_fmask = Mmask(oo_src, oo_fvec, kind=1, ml=ml).mt_binarize()
    oo_bmask = Mmask(oo_src, oo_bvec, kind=1, ml=ml).mt_binarize()

    fmask_2   = Interleave(ee_fmask, oo_fmask)
    bmask_2   = Interleave(ee_bmask, oo_bmask)
    background = mt_logic(fmask_2.SelectEvery(1,1),
\                         bmask_2.SelectEvery(1,-1),
\                         mode="or")
    stable_blink = mt_hysteresis(background.mt_invert, blink)
    blink2 = (STABILIZE) ? stable_blink : blink

# Shrinking the blink mask can get rid of noise,
# too much will lose signal as well.
    blink3 = blink2.mt_inpand(mode=mt_diamond(inpand))
   
# Using just pixels that changed helps sharpen the mask
    diff   = ng_diff(clp.SelectEvery(1,-1), clp)
    diff_2 = mt_logic(diff, diff.SelectEvery(1,1), mode="and")

#Hysteresis
# Matches continuous blocks of pixels.
# Use with care, will match the whole screen on fades.
    hyster_blink = mt_hysteresis(blink3, diff_2)

# Expand the mask to make up for shrinking it (or just use hysteresis)
    blink4 = blink3.mt_expand(mode=mt_circle(expand))
    sharp_blink = mt_logic(blink4, diff_2, mode="and")

    blink5 = (HYSTER) ? hyster_blink :
\            (SHARP)  ? sharp_blink  : blink4

   
# A flash won't match blocks 1 or 2 frames away.
    sub_flash = mt_logic(fmask_2, bmask_2, mode="and")
    flash     = mt_logic(blink, sub_flash, mode="and")
   
# A shake changes in one frame and changes back in the next.
# This isn't detected by the motion vectors because the blocks exist in
# both frames, they are just shifting around.
    same   = ng_same(clp.SelectEvery(1,-1), clp.SelectEvery(1,1))
    shake  = mt_logic(same, diff_2, mode="and")

    (TEST) ? stackhorizontal(clp, mergeRGB(blink5, flash, shake))
\          : blink5.GreyScale()
}

function ng_diff(clip A, clip B, int "thr"){
    thr=default(thr,0)
    TAD=ng_TAD(A,B)
    return mt_binarize(TAD, threshold=thr)
}

function ng_same(clip A, clip B, int "thr"){
    thr=default(thr,0)
    TAD=ng_TAD(A,B)
    return mt_binarize(TAD, threshold=thr, upper=true)
}

function ng_TAD(clip A, clip B){
    R=ng_AD(A  .showRed("YV12"),B  .showRed("YV12"))
    G=ng_AD(A.showGreen("YV12"),B.showGreen("YV12"))
    B=ng_AD(A .showBlue("YV12"),B .showBlue("YV12"))
    return ng_plus(R, ng_plus(G, B))
}

function ng_AD(clip A, clip B){
    return mt_lutxy(A,B,"x y - abs")
}

function ng_plus(clip A, clip B){
    return mt_lutxy(A,B,"x y +")
}
--- Конец кода ---
Valet2:
Пожалуйста, по-русски.

Если имеется в виду, что на приставке для имитации цвета используется быстрое мигание двух других цветов, и при конвертации во вдвое меньший фреймрейт исчезнет всё это, то можно конвертировать через тот же Вегас - по умолчанию там включен smart resample для дорожки - он просто два кадра смешивает. Если приглядеться, будет немного смазанным в движении, но зато информация с обоих кадров останется.
Partsigah:
Этот код в "extra command line" вставлять, в настройках x264vfw?
feos:
Valet2, дак я жи говорю, между кадрами смешивается только сам мигающий объект и только когда он мигает. Все прочее остается идеально четким. Например пламя в Gunstar Heroes:


Partsigah, это часть скрипта AviSynth. Позже целиком скрипт дам.
Gilroy:

--- Цитата: feos от 03 Март 2013, 17:15:16 ---Можно руками вписать разрешение 960x720, тогда будет и 4:3, и HD.
--- Конец цитаты ---

Не знаю, как у всех остальных, но у меня FCEUX 2.2.0 захватывает в разрешении 256×224. Если выставить в VirtualDub'е 960x720, нарушатся пропорции.

Откуда у всех берётся 320×240, объясните мне, тупому.
feos:
Ниоткуда не берется, это ютуб пережимает.

А пропорции не нарушаются, он становятся как на телеке.
Gilroy:
Тут всё правильно я выставил?

Valet2:
Ты выставил проценты, а не разрешение!
Навигация
Главная страница сообщений
Следующая страница

Перейти к полной версии