From e481fe87e8d386a6ace5f142e1c0c4a557e4f185 Mon Sep 17 00:00:00 2001 From: Fagear Date: Fri, 11 Nov 2022 01:40:41 +0300 Subject: [PATCH] PCM-1 manual offset, fixed STC-007 CWD, GUI fixes Added manual vertical data offset control for PCM-1, fixed PCM-1 stray header line processing as audio, fixed STC-007 CWD, added display for STC-007 address code, moved VU-envelope generation into AudioProcessor to reduce GUI lagging, small AudioProcessor rework to support advanced interpolation modes in the future, visualizer optimizations, added new tooltips and translations. --- SDVPCMdecoder.pro | 6 +- SDVPCMdecoder_en.ts | 1372 ++++++++++++++++------------ SDVPCMdecoder_pl.ts | 1373 ++++++++++++++++------------ about_wnd.ui | 2 +- audioprocessor.cpp | 240 +++-- audioprocessor.h | 36 +- binarizer.h | 4 +- capt_sel.cpp | 8 +- capt_sel.ui | 140 ++- config.h | 4 +- ffmpegwrapper.cpp | 25 +- fine_deint_set.ui | 4 +- frame_vis.cpp | 43 +- frame_vis.h | 8 +- frame_vis.ui | 4 +- frametrimset.cpp | 17 + frametrimset.h | 6 + mainwindow.cpp | 666 +++++++------- mainwindow.h | 131 ++- mainwindow.ui | 518 ++++++++--- pcm16x0datastitcher.cpp | 79 +- pcm16x0deinterleaver.cpp | 8 +- pcm16x0subline.cpp | 9 +- pcm1datastitcher.cpp | 239 ++++- pcm1datastitcher.h | 6 + pcm1deinterleaver.cpp | 4 +- pcm1line.cpp | 9 +- pcmsamplepair.cpp | 124 ++- pcmsamplepair.h | 38 +- renderpcm.cpp | 148 ++-- renderpcm.h | 14 +- samples2wav.cpp | 316 ++++--- samples2wav.h | 23 +- stc007datablock.cpp | 257 +++--- stc007datablock.h | 6 +- stc007datastitcher.cpp | 1821 +++++++++++++++++++------------------- stc007datastitcher.h | 8 +- stc007deinterleaver.cpp | 166 ++-- stc007line.cpp | 52 +- videotodigital.cpp | 16 +- vin_ffmpeg.cpp | 7 +- vin_ffmpeg.h | 1 + 42 files changed, 4620 insertions(+), 3338 deletions(-) diff --git a/SDVPCMdecoder.pro b/SDVPCMdecoder.pro index 3107185..b8cebc3 100644 --- a/SDVPCMdecoder.pro +++ b/SDVPCMdecoder.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui winextras +QT += core gui opengl winextras greaterThan(QT_MAJOR_VERSION, 4): QT += widgets multimedia concurrent @@ -28,10 +28,10 @@ QMAKE_CFLAGS_RELEASE += -O3 -march=pentium3m QMAKE_CXXFLAGS+= -D__STDC_CONSTANT_MACROS -fpermissive -VERSION = 0.99.5 +VERSION = 0.99.6 win32: QMAKE_TARGET_COMPANY = Fagear win32: QMAKE_TARGET_PRODUCT = SD video PCM decoder -win32: QMAKE_TARGET_DESCRIPTION = SD video to digital audio PCM decoder +win32: QMAKE_TARGET_DESCRIPTION = SD video to digital audio decoder win32: QMAKE_TARGET_COPYRIGHT = (c) Fagear win32: RC_LANG = 0x0419 diff --git a/SDVPCMdecoder_en.ts b/SDVPCMdecoder_en.ts index 29c02f0..b55fc15 100644 --- a/SDVPCMdecoder_en.ts +++ b/SDVPCMdecoder_en.ts @@ -4,7 +4,7 @@ MainWindow - + Настройки декодера Decoder settings @@ -35,188 +35,188 @@ Detect repeating lines - - - - + + + + Метод бинаризации (определение "0" и "1" в видео) Binarization method (video to "0" and "1" conversion) - + Бинаризация: Binarization: - + экстремальная (медленно) extreme (slow) - + качественная quality - + быстрая fast - + черновая draft - - - - + + + + Формат входного видео (число строк и частота кадров) Source video format (line count and frame rate) - + Строк в кадре: Lines per frame: - - - - - - - + + + + + + + автоматически automatically - + 525 (NTSC, 2x245) 525 (NTSC, 2x245) - + 625 (PAL, 2x294) 625 (PAL, 2x294) - - - - - - - - - - - - + + + + + + + + + + + + Порядок полей в кадрах исходного видео Field order in source video - - - - - - + + + + + + Порядок полей: Field order: - - - + + + TFF (сначала нечётное) TFF (odd first) - - - + + + BFF (сначала чётное) BFF (even first) - - - - + + + + Разрешённые ступени исправления ошибок CRC (Q-код доступен только для 14 бит) Enabled stages of CRC error correction (Q-code is available only in 14-bit mode) - - + + Коррекция ошибок: Error correction: - - + + отключена disabled - - - - + + + + Действие с выпадениями (неисправимыми аудио-отсчётами) Dropout masking (for uncorrected audio samples) - + Выпадения: Dropouts: - + интерполировать по отсчётам interpolate by samples - + интерполировать по блокам interpolate by blocks - + держать уровень по отсчётам hold by samples - + держать уровень по блокам hold by blocks - + заглушать по блокам mute by blocks - + пропускать (не маскировать) ignore (don't mask) - - + + Разрешение аудио: Audio resolution: - + 14 бит (STC-007) 14 bits (STC-007) - + 16 бит (PCM-F1) 16 bits (PCM-F1) @@ -227,118 +227,120 @@ Path to source video file - - - - - - + + + + + + Параметры нечётного поля видео сигнала Odd field parameters - - - + + + + Нечётное поле: Odd field: - - - - - - + + + + + + Параметры чётного поля видео сигнала Even field parameters - - - + + + + Чётное поле: Even field: - - - - - - + + + + + + Номер строки, с которой начинаются PCM-данные First line with PCM data - - - + + + Начальная строка: First line: - - - - - - + + + + + + Начальная строка PCM-данных в нечётном поле First line with PCM data in odd field - - - - - - + + + + + + Начальная строка PCM-данных в чётном поле First line with PCM data in even field - - + + Разрешение аудио в нечётном поле Audio resolution in odd field - - + + Разрешение аудио в чётном поле Audio resolution in even field - + Внутри кадра: In-frame: - + Между кадрами: Inter-frame: - + Количество строк, которое необходимо вставить между полями Number of lines to be inserted between fields - + Дополнение строк: Line padding: - - - - + + + + Установленный стандарт исходного видео Detected video standard - + Стандарт видео: Video standard: @@ -424,161 +426,161 @@ Pause - + Статистика Statistics - - + + Сброс статистики Reset counters - + Сброс Reset - - - - + + + + Число считанных кадров Number of frames read from the source - + Считано кадров: Read frames: - - - - + + + + Число кадров, выпавших в исходном видео Number of dropped frames - + Выпавших кадров: Dropped frames: - - + + Содержание PCM-данных в кадре Percent of lines with PCM data in a frame - - + + Соотношение сигнал/шум PCM данных Signal to noise ratio within PCM data lines - - - - + + + + Число полностью обработанных кадров Number of fully processed frames - + Обработано кадров: Processed frames: - - + + Заполненность буфера видео-строк Video-lines buffer fill - - + + Текущий уровень порога бинаризатора Current binarization threshold - - + + Текущий уровень порога бинаризатора (0...255) Current binarization threshold (0...255) - + Пороговый уровень: Threshold level: - - - - + + + + Число видео-строк без PCM Number of video lines without PCM data - + Пустые строки (без PCM): Empty lines (no PCM data): - - - - + + + + Число видео-строк с ошибками Number of video lines with errors - + Повреждённые строки (CRC): Damaged lines (CRC): - - + + Число видео-строк, одинаковых с предшествующими Number of repeated video lines - - + + Число видео-строк, одинаковых с предшествующими (возможные ошибки из-за компенсаторов выпадений) Number of repeated video lines (possible errors due to a dropout compensator in a VTR) - + Дубликатов строк: Repeated lines: - - + + Заполненность буфера бинаризированных PCM-строк PCM-lines buffer fill - - - - + + + + Число сшивок полей, на которых не удалось проверить корректность сборки блоков данных Field stitching: process of iterative detection of how many lines to insert between adjacent fields to assemble full frame. Number of field stitches which were not verified for valid data block assembly - + Непроверенных сшивок полей: Field stitching: process of iterative detection of how many lines to insert between adjacent fields to assemble full frame. @@ -586,71 +588,71 @@ lines (CRC): field stitches: - - - - + + + + Число блоков данных, в которых успешно исправлена одиночная ошибка Number of data blocks in which single-sample error was corrected - + Успешных P-коррекций: Successfull P-corrections: - - - - + + + + Число блоков данных, в которых успешно исправлена двойная ошибка Number of data blocks in which double-sample errors were corrected - + Успешных Q-коррекций: Successfull Q-corrections: - - - - + + + + Число блоков данных, которые невозможно восстановить кодами P и Q Number of data blocks that were not corrected with P and Q codes - + Неисправленных блоков данных: Uncorrectable data blocks: - - + + Заполненность буфера PCM блоков данных Data blocks buffer fill - - - - + + + + Формат кодирования PCM в исходном видео-файле PCM format in the source video file - + Формат PCM: PCM format: - + STC-007/Sony PCM-F1 STC-007/PCM-F1 STC-007/Sony PCM-F1 @@ -662,55 +664,55 @@ data blocks: Automatic pause after every video frame - - - - + + + + Разрешение декодируемого аудио (будет приведено к 16 битам на выходе) Resolution of output audio (it will be converted to 16 bits) - - - - - - - - + + + + + + + + Частота отсчётов декодируемого аудио (будет записана в заголовок WAV) Sample rate of output audio (it will be written into WAV header) - - + + Частота отсчётов: Sample rate: - - + + 44056 Гц 44056 Hz - - + + 44100 Гц 44100 Hz - + SI-формат SI format - + EI-формат EI format - + Режим PCM-1630: PCM-1630 mode: @@ -720,834 +722,930 @@ data blocks: SDVPCM: SD video to PCM audio decoder - Вставка сверху: - Top padding: + Top padding: - Вставка снизу: - Bottom padding: + Bottom padding: - - - - + + + + Режим кодирования PCM-1630 Encoding mode for PCM-1630 - - - - + + + + Разрешение исправления ошибок CRC кодами коррекции Enable CRC error correction - + включена (P-код) enabled (P-code) - + полная (P и Q коды) full (P and Q codes) - + частичная (P-код) partial (P-code) - - + + Активация дополнительной коррекции Cross-Word Decoding Enable Cross-Word Decoding error correction assist - + CWD коррекция CWD assist - + CWD отключено CWD disabled - + заглушать по отсчётам mute by samples - + PCM-1 (Sony Standard B) PCM-1 (Standard B) PCM-1 (Sony Standard B) - + PCM-16x0 (Sony Standard A) PCM-16x0 (Standard A) PCM-16x0 (Sony Standard A) - - - - + + Применение коррекции АЧХ Apply frequency response correction - + Деэмфазис: De-emphasis: - + + + Функционал ещё не готов + This feature is not ready yet + + + включён enabled - + отключён disabled - + Параметры сборки кадра PCM-1 Frame assembling parameters for PCM-1 - - - - - - + + + + + + Количество строк, в которых могут быть PCM-данные Number of lines that can contain PCM data - - - + + + Строк данных: Lines with data: - - - - + + + + Количество строк, которое необходимо вставить выше PCM-данных в нечётном поле Number of lines to be inserted above PCM data in the odd field - - - - + + + + Количество строк, которое необходимо вставить выше PCM-данных для корректной сборки кадра Number of lines to be inserted above PCM data for valid frame assembling - - + + Дополнение сверху: Top padding: - - - - + + + + Количество строк, которое необходимо вставить ниже PCM-данных в нечётном поле Number of lines to be inserted below PCM data in the odd field - - - - + + + + Количество строк, которое необходимо вставить ниже PCM-данных для корректной сборки кадра Number of lines to be inserted below PCM data for valid frame assembling - - + + Дополнение снизу: Bottom padding: - - - - - - - - - - - - + + + + + + + + + + + + Установленный порядок полей в кадре Field order in the frame - - - - - - - - - - - - + + + + + + + + + + + + Номер кадра исходного видео, для которого применяются параметры сборки Number of the frame that listed assembly parameters apply to - - - + + + Номер кадра: Frame number: - - - - + + + + Количество строк, которое необходимо вставить выше PCM-данных в чётном поле Number of lines to be inserted above PCM data in the even field - - - - + + + + Количество строк, которое необходимо вставить ниже PCM-данных в чётном поле Number of lines to be inserted below PCM data in the even field - - - - - - + + + + + + Количество строк PCM-данных в нечётном поле Number of lines with PCM data in the odd field - - - - - - + + + + + + Количество строк PCM-данных в чётном поле Number of lines with PCM data in the even field - - - + + + + + + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + Averaged by the frame horizontal data coordinates (in pixels) + + + + + Координаты: Coordinates: - + + + + + + + Усреднённые по кадру координаты начала данных (в пикселях) + Averaged by the frame data start coordinates (in pixels) + + + + + + + + + Усреднённые по кадру координаты конца данных (в пикселях) + Averaged by the frame data stop coordinates (in pixels) + + + Параметры сборки кадра PCM-1600/PCM-1610/PCM-1630 Frame assembling parameters for PCM-1600/PCM-1610/PCM-1630 - - - - + + + + Формат данных PCM-1630 PCM-1630 data encoding - + Формат данных: Data encoding: - + Параметры сборки кадра STC-007/PCM-F1 Frame assembling parameters for STC-007/PCM-F1 - - + + Установленное разрешение аудио Audio resolution - - + + Вставка строк между PCM-данными из полей одного кадра Line padding between PCM data chunks from the fields of one frame - + Количество строк, которое необходимо вставить между PCM-данными соседних полей для корректной сборки кадра Number of lines to be inserted between PCM data chunks from adjacent fields for valid frame assembling - - + + Вставка строк между PCM-данными из смежных полей соседних кадров Line padding between PCM data chunks from adjacent frames - - - - + + + + Общее число кадров в источнике Total number of frames in the video - + Всего кадров: Total frames: - - - - + + + + Число блоков данных, не имеющих ошибок по CRC, но не прошедшие проверку по P и Q словам Number of data blocks that have no CRC errors but did not pass integrity check with P and Q words - + "Сломанных" блоков данных: "Broken" data blocks: - - - - + + + + + Число блоков данных, в которых успешно исправлены ошибки с помощью Cross-Word Decoding + Number of data blocks in which error was corrected with Cross-Word Decoding assistance + + + + Успешных +CWD-коррекций: + Successfull +CWD-corrections: + + + + + + Число аудио-отсчётов, которые невозможно восстановить кодами P и Q Number of audio samples that were not corrected with P and Q codes - + Неисправленных аудио-отсчётов: Uncorrectable audio samples: - - - - + + + + Число аудио-отсчётов, в которых замаскировано выпадение Number of masked dropouts - + Маскировано аудио-отсчётов: Masked audio samples: - - - - Число аудио-отсчётов, в которых заглушено выпадение - Number of muted dropouts + Number of muted dropouts - Заглушено аудио-отсчётов: - Muted + Muted audio samples: - + Отладка: время выполнения Debug: run time - + Файл File - + Отладка Debug - - - - - - - - - - + + + + + + + + + + Вывод отладочной информации в консоль Output debug information into a console - + Сырые данные при бинаризации Raw data while binarizing - + Сбросить настройки декодирования в главном окне Reset decoder settings in the main window - + Отключиться от захвата Disconnect from the source - + Захватить PCM с видео захвата... Capture PCM from a capture device... - + Захват видео с устройства для декодирования PCM Capture video from a device for PCM decoding - + Закрыть источник Close source - + Отключиться от выбранного источника видео Disconnect from selected video source - + Координаты данных Data coordinates - + Деинтерливинг, пересборка кадров Deinterleaving and frame re-assembly - + Общее General - - + + Запуск фоновых процессов тестирования внутренних вычислений Launch background tests of internal calculations and logic - + Вычислительные тесты Computation tests - + Обработка и вывод аудио Audio processing and output - + Настройки Settings - - + + Выбор языка интерфейса Select user interface language - + Язык интерфейса Interface language - + Визуализация Visualization - + Справка Help - + Это строка состояния, здесь выводятся подсказки This is the status bar with help tips - + Открыть видео с PCM... Open a video file with PCM... - + Открытие видео-файла поддерживаемого формата, содержащего PCM Open dialog for selecting supported video file with PCM data - + Диалог открытия файла изображения, содержащего PCM Диалог открытия видео-файла поддерживаемого формата, содержащего PCM Open a dialog for selecting an image file with PCM data - + Открыть изображение с PCM... Open image file with PCM... - + + + Индикатор уровня аудио, левый канал + Audio level meter, left channel + + + + + Индикатор уровня аудио, правый канал + Audio level meter, right channel + + + + + + + + + Смещение (в строках) данных от верха чётного поля + Offset (in lines) of the data from the top of the even field + + + + + + + + + Смещение (в строках) данных от верха нечётного поля + Offset (in lines) of the data from the top of the odd field + + + + + Параметры смещения данных в полях по вертикали + Vertical data offset parameters + + + + Смещение сверху: + Vertical offset: + + + + + Попытаться автоматически выровнять данные в полях по высоте (результат не гарантирован) + Try to automatically vertically align data in the fields (result in not guaranteed) + + + + Автоматически по содержимому + Automatically by content + + + Захват и декодирование видео Video capturing and decoding - + Поиск данных, бинаризация Data search, binarization - + Выход Exit - + Закрыть приложение Close application - + Данные по кадрам Frame data - + Данные по строкам Line data - + Данные по пикселям Pixel data - - - - - + + + + + Общий процесс General process - + Статистика распределения яркостей Brightness spread statistics - + Полный процесс подбора порога бинаризации Full reference level sweep process - + Выключить весь вывод отладки Turn off all debug output - + Отключить вывод всей отладки в консоль Turn off all debug output - + Дампы обработанных PCM-строк Processed PCM-lines dump - + Дампы обработанных блоков данных Processed data blocks dump - - - - - + + + + + Ввод настроек Settings changes - - - - - + + + + + Выключить все Turn off all above - + Дамп полей при подборе вставки Field dump while line-padding detection - + Дамп блоков данных при подборе вставки Data block dump while line-padding detection - + Подбор вставок для полей кадра Padding detection for fields - + Определение границ PCM в кадре Frame trimming - + Преобразование строк в блоки данных PCM-lines to data blocks conversion - + Проверить подсчёт CRCC Check CRCC calculation - + Проверить работу ECC STC-007 (корректора ошибок) Check STC-007 ECC (error correcting) processing - + Операции глушения и маскирования Masking and muting operations - + Дамп буфера аудио Audio samples buffer dump - + Сохранение в файл Saving to a file - + Пересборка кадров со вставками Frame re-assembly with padding - + Исправление ошибок по P и Q кодам Error correction with P and Q codes - + Вывод аудио в звуковой интерфейс Realtime audio output - + Тонкие настройки бинаризатора... Fine binarizator settings... - + Открыть диалог тонкой настройки бинаризатора Open binarizator fine settings dialog - + Тонкие настройки деинтерливера... Fine deinterleaver settings... - + Открыть диалог тонкой настройки деинтерливера Open deinterleaver fine settings dialog - + Тонкие настройки видео-декодера... Fine video decoder settings... - + Открыть диалог тонкой настройки видео-декодера Open video decoder fine settings dialog - + О программе... About... - + Открытие окна с информацией о программе Open window with additional information about the software - + Сбросить все настройки Reset all settings - + Сбросить все настройки приложения (включая последнюю папку и положения окон) Reset all application settings (including last folder and windows positions) - + Сбросить положения окон Reset visualization positions - + Сбросить настройки декодера Reset decoder settings - + Источник видео Video source - + Бинаризированные кадры Binarized frames - + Пересобранные кадры Re-assembled frames - + Блоки данных Data blocks - - - + + + Ошибка Error - + Открыть видео с PCM Open video with PCM - + Видео-файлы (*.avi *.mkv *.mpg *.mp4) Video files (*.avi *.mkv *.mpg *.mp4) - - + + Сброс настроек Settings reset - + Сброс настроек декодера Reset decoder settings - + Вернуть настройки к состоянию по умолчанию? Reset settings to defaults? - + Сброс расположения Reset positions - + Сброс расположения окон визуализации Reset visualization windows positions - + Сбросить положения окон визуализации? Reset all visualization windows positions? - + Сброс ВСЕХ настроек Reset ALL settings - + Вернуть ВСЕ настройки программы к состоянию по умолчанию? Reset everything to defaults? - - + + Результат Result - + Тест CRCC пройден успешно. CRCC test passed successfully. - + Тест CRCC не пройден! Подробности в отладочной консоли. CRCC test failed! See debug console. - + Тест ECC пройден успешно. ECC test passed successfully. - + Тест ECC не пройден! Подробности в отладочной консоли. ECC test failed! See debug console. @@ -1555,98 +1653,98 @@ audio samples: QObject - - + + не определён not defined - + TFF, нечётное поле первое TFF, odd field first - + BFF, чётное поле первое BFF, even field first - + (форсировано) (forced) - + NTSC (525i), 245 строк с PCM в поле NTSC (525i), 245 PCM lines per field - + PAL (625i), 294 строк с PCM в поле PAL (625i), 294 PCM lines per field - + Формат SI SI format - + Формат EI EI format - + (форсирован) (forced) - + 14 бит (STC-007) 14 bits (STC-007) - + 14 бит (неточно) 14 bits (not certain) - + 16 бит (неточно) 16 bits (not certain) - + 16 бит (PCM-F1) 16 bits (PCM-F1) - + Источник видео Video source - + Бинаризированные кадры Binarized frames - + Пересобранные кадры Re-assembled frames - + Блоки данных Data blocks - + Для использования меню отладки запустите приложение из коммандной строки Launch application from a command line to get access to the debug menu - + Кадр: Frame: @@ -1666,80 +1764,112 @@ audio samples: Windows DirectShow screen capture + + SamplesToWAV + + + Вывод в WAV: не удалось открыть на запись файл ' + Output to WAV: failed to open for writing file ' + + + + Вывод в WAV: не удалось добавить заголовок, файл не открыт! + Output to WAV: failed to add header, file is not open! + + + + Вывод в WAV: не удалось добавить заголовок в файл! + Output to WAV: failed to add header to the file! + + + + + + + + Вывод в WAV: не удалось обновить заголовок в файле! + Output to WAV: failed to update header in the file! + + + + Вывод в WAV: не удалось записать аудио данные в файл! + Output to WAV: failed to write audio data to the file! + + VideoInFFMPEG - + Указанный файл источника не найден! Source file does not exist! - + Недостаточно прав для чтения файла источника! Not enough permissions to read the file! - + FFMPEG: Не удалось открыть файл FFMPEG: Failed to open the file - + FFMPEG: Не удалось получить информацию о потоке видео FFMPEG: Failed to find stream information - + FFMPEG: Не удалось найти поток видео FFMPEG: Failed to find video stream in the source - + FFMPEG: Не удалось найти декодер для видео FFMPEG: Failed to find decoder for the video stream - + FFMPEG: Не удалось выделить ОЗУ для декодера видео FFMPEG: Failed to allocate RAM for video decoder - + FFMPEG: Не удалось установить параметры для декодера видео FFMPEG: Failed to apply parameters to video decoder - + FFMPEG: Не удалось запустить декодер видео FFMPEG: Failed to start the video decoder - + FFMPEG: Не удалось выделить ОЗУ для буфера кадра FFMPEG: Failed to allocate RAM for the frame buffer - + FFMPEG: Не удалось считать пакет данных из декодера FFMPEG: Failed to read a data packet from the decoder - + FFMPEG: Не удалось инициализировать преобразователь кадра FFMPEG: Failed to initialize frame converter - + FFMPEG: Не удалось преобразовать формат кадра видео FFMPEG: Failed to convert format of the video frame - + FFMPEG: Не задан источник видео FFMPEG: Video source is not set - + FFMPEG: Неизвестная ошибка чтения видео FFMPEG: Unknown error @@ -1759,9 +1889,9 @@ audio samples: - <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> - <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, STANDARD B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, STANDARD A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> - <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 channels, 13 bits, 44056 Hz, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 channels, 16 bits, 44056 Hz, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 channels, 16 bits, 44056/4410 Hz, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 channels, 16 bits, 44056/44100 Hz, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 channels, 14 bits, 44056 Hz, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 channels, 14 bits, 44100 Hz, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 channels, 16 bits, 44056/44100 Hz, NTSC/PAL)</p></body></html> + <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, Sony PCM-F1, NTSC/PAL)</p></body></html> + <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> + <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 channels, 13 bits, 44056 Hz, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 channels, 16 bits, 44056 Hz, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 channels, 16 bits, 44056/44100 Hz, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 channels, 16 bits, 44056/44100 Hz, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 channels, 14 bits, 44056 Hz, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 channels, 14 bits, 44100 Hz, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 channels, 16 bits, 44056/44100 Hz, Sony PCM-F1, NTSC/PAL)</p></body></html> @@ -1813,189 +1943,309 @@ audio samples: + + Разрешение захватываемого изображения + Resolution of the captured video + + + Разрешение: Resolution: - - - - + + + Смещение левого верхнего угла конечного кадра по горизонтали + Horizontal offset of the top left corner of the target frame + + + + + + пикс. pixels - + + + Горизонтальное разрешение захватываемого изображения + Horizontal resolution of the captured video + + + + + + + Частота кадров в секунду для захвата + Number of frames per second to capture + + + кадр/сек fps - + + + Установить параметры захвата для PAL видео + Preset parameters for PAL video capture + + + + + + + Параметры, с которыми производится захват (могут отличаться от заданных из-за ограничений устройства захвата) + Applied capture parameters (can differ from preset ones due to capture device limitations) + + + Применено: Applied: - + + + Установить параметры захвата по видео стандарту + Preset standard parameters for video capture + + + Предустановка: Preset: - + Частота кадров: Framerate: - + + + Смещение левого верхнего угла конечного кадра от кадра источника + Offset of the top left corner of the target frame from the source frame + + + Смещение: Offset: - + + + Установить параметры захвата для NTSC видео + Preset parameters for NTSC video capture + + + + + Вертикальное разрешение захватываемого изображения + Vertical resolution of the captured video + + + + + Смещение левого верхнего угла конечного кадра по вертикали + Vertical offset of the top left corner of the target frame + + + + + Применить настройки выше для текущего выбранного устройства + Apply settings above for the selected capture device + + + Применить Apply - + + + Оставить настройки захвата по умолчанию + Keep using default capture device settings + + + Настройки устройства по умолчанию Device defaults - + + + + + Используемый для захвата изображения цветовой канал + Color channel used for video capture + + + Яркость (канал Y) Brightness (Y channel) - + Красный (канал R) Red (R channel) - + Зелёный (канал G) Green (G channel) - + Синий (канал B) Blue (B channel) - + Цветовой канал: Color channel: - + Доступные устройства захвата видео Available video capture devices - + + + Список доступных в системе устройств захвата видео + List of available video capture devices in the system + + + + + Запросить актуальный список устройств захвата + Get a list of currently available capture devices + + + Обновить список Refresh the list - + Предпросмотр (чёрно-белый) Preview (black and white) - + + + Предпросмотр устройства захвата в реальном времени + Real-time capture device preview + + + + + Функционал ещё не готов + This feature is not ready yet + + + Сохранить Save - + + + Закрыть окно без сохранения изменений + Close this window without saving any settings + + + Закрыть Close - + Список обновляется... List is updating... - + Ошибка Error - + Не получен вовремя ответ от FFMPEG, возможно библиотека зависла. Didn't get respond from FFMPEG in time, probably it has hung - + Нет устройств захвата видео No capture devices - + Устройство не выбрано Device not selected - + FFMPEG: Не удалось открыть захват с заданными параметрами FFMPEG: Failed to open the capture device with provided parameters - + FFMPEG: Не удалось получить информацию о потоке видео FFMPEG: Failed to find stream information - + FFMPEG: Не удалось найти поток видео FFMPEG: Failed to find video stream in the source - + FFMPEG: Не удалось найти декодер для видео FFMPEG: Failed to find decoder for the video stream - + FFMPEG: Не удалось выделить ОЗУ для декодера видео FFMPEG: Failed to allocate RAM for video decoder - + FFMPEG: Не удалось установить параметры для декодера видео FFMPEG: Failed to apply parameters to video decoder - + FFMPEG: Не удалось запустить декодер видео FFMPEG: Failed to start the video decoder - + FFMPEG: Не удалось выделить ОЗУ для буфера кадра FFMPEG: Failed to allocate RAM for the frame buffer - + FFMPEG: Не удалось считать пакет данных из декодера FFMPEG: Failed to read a data packet from the decoder - + FFMPEG: Не удалось инициализировать преобразователь кадра FFMPEG: Failed to initialize frame converter - + FFMPEG: Не удалось преобразовать формат кадра видео FFMPEG: Failed to convert format of the video frame - + FFMPEG: Неизвестная ошибка захвата видео FFMPEG: Unknown capture error - + Ошибка захвата видео Video capture error diff --git a/SDVPCMdecoder_pl.ts b/SDVPCMdecoder_pl.ts index 23d2e0e..9e105f5 100644 --- a/SDVPCMdecoder_pl.ts +++ b/SDVPCMdecoder_pl.ts @@ -24,7 +24,7 @@ - + Настройки декодера Ustawienia dekodera @@ -55,188 +55,242 @@ Wykrywanie zduplikowanych linii - - - - + + + Индикатор уровня аудио, левый канал + + + + + + Индикатор уровня аудио, правый канал + + + + + + + + + + Смещение (в строках) данных от верха чётного поля + + + + + + + + + + Смещение (в строках) данных от верха нечётного поля + + + + + + Параметры смещения данных в полях по вертикали + + + + + Смещение сверху: + + + + + + Попытаться автоматически выровнять данные в полях по высоте (результат не гарантирован) + + + + + Автоматически по содержимому + + + + + + + Метод бинаризации (определение "0" и "1" в видео) Metoda binaryzacji (konwersja wideo na "0" i "1") - + Бинаризация: Binaryzacja: - + экстремальная (медленно) dokładna (wolno) - + качественная normalna - + быстрая szybka - + черновая niedokładna - - - - + + + + Формат входного видео (число строк и частота кадров) Format źródłowego wideo (liczba linii i klatek na sekundę) - + Строк в кадре: Linie na klatkę: - - - - - - - + + + + + + + автоматически automatycznie - + 525 (NTSC, 2x245) 525 (NTSC, 2x245) - + 625 (PAL, 2x294) 625 (PAL, 2x294) - - - - - - - - - - - - + + + + + + + + + + + + Порядок полей в кадрах исходного видео Kolejność pól w klatkach oryginalnego wideo - - - - - - + + + + + + Порядок полей: Kolejność pól: - - - + + + TFF (сначала нечётное) TFF (najpierw górne) - - - + + + BFF (сначала чётное) BFF (najpierw dolne) - - - - + + + + Разрешённые ступени исправления ошибок CRC (Q-код доступен только для 14 бит) Dozwolone kroki korekcji błędów CRC (Q-kod jest dostępny tylko dla 14 bit) - - + + Коррекция ошибок: Korekcja błędów: - - + + отключена wyłączona - - - - + + + + Действие с выпадениями (неисправимыми аудио-отсчётами) Akcja dla zakłóceń (nieprawidłowy blok danych) - + Выпадения: Zakłócenia: - + интерполировать по отсчётам interpolacja z próbek - + интерполировать по блокам interpolacja z bloków - + держать уровень по отсчётам powtarzanie próbek - + держать уровень по блокам powtarzanie bloków - + заглушать по блокам wyciszanie bloków - + пропускать (не маскировать) ignorowanie (nie maskuj) - - + + Разрешение аудио: Rozdzielczość dźwięku: - + 14 бит (STC-007) 14 bit (STC-007) - + 16 бит (PCM-F1) 16 bit (PCM F-1) @@ -247,118 +301,120 @@ Ścieżka do źródłowego pliku wideo - - - - - - + + + + + + Параметры нечётного поля видео сигнала Parametry dolnego pola - - - + + + + Нечётное поле: Dolne pole: - - - - - - + + + + + + Параметры чётного поля видео сигнала Parametry górnego pola - - - + + + + Чётное поле: Górne pole: - - - - - - + + + + + + Номер строки, с которой начинаются PCM-данные Pierwsza linia z danymi PCM - - - + + + Начальная строка: Pierwsza linia: - - - - - - + + + + + + Начальная строка PCM-данных в нечётном поле Pierwsza linia z danymi PCM w dolnym polu - - - - - - + + + + + + Начальная строка PCM-данных в чётном поле Pierwsza linia z danymi PCM w górnym polu - - + + Разрешение аудио в нечётном поле Rozdzielczość dźwięku w dolnym polu - - + + Разрешение аудио в чётном поле Rozdzielczość dźwięku w górnym polu - + Внутри кадра: W klatce: - + Между кадрами: Między klatkami: - + Количество строк, которое необходимо вставить между полями Liczba pustych linii do wstawienia między pola - + Дополнение строк: Puste linie: - - - - + + + + Установленный стандарт исходного видео Wykryty standard wideo - + Стандарт видео: Standard wideo: @@ -428,231 +484,231 @@ Pauza - + Статистика Statystyki - - + + Сброс статистики Wyzeruj liczniki - + Сброс Reset - - - - + + + + Число считанных кадров Liczba odczytanych klatek ze źródła - + Считано кадров: Klatki odczytane: - - - - + + + + Число кадров, выпавших в исходном видео Liczba opuszczonych klatek - + Выпавших кадров: Klatki opuszczone: - - + + Содержание PCM-данных в кадре Procent linii z danymi PCM w klatce - - + + Соотношение сигнал/шум PCM данных Odstęp sygnału od szumu w liniach danych PCM - - - - + + + + Число полностью обработанных кадров Liczba przetworzonych klatek - + Обработано кадров: Klatki przetworzone: - - + + Заполненность буфера видео-строк Zapełnienie bufora linii wideo - - + + Текущий уровень порога бинаризатора Bieżący próg binaryzacji - - + + Текущий уровень порога бинаризатора (0...255) Aktualny próg binaryzacji (0...255) - + Пороговый уровень: Próg poziom: - - - - + + + + Число видео-строк без PCM Liczba linii wideo bez danych PCM - + Пустые строки (без PCM): Puste linie (bez PCM): - - - - + + + + Число видео-строк с ошибками Liczba linii wideo z błędami - + Повреждённые строки (CRC): Uszkodzone linie (CRC): - - + + Число видео-строк, одинаковых с предшествующими Liczba powtórzonych linii wideo - - + + Число видео-строк, одинаковых с предшествующими (возможные ошибки из-за компенсаторов выпадений) Liczba powtórzonych linii wideo (możliwe błędy spowodowane przez kompensator zakłóceń magnetowidu) - + Дубликатов строк: Linie powtórzone: - - + + Заполненность буфера бинаризированных PCM-строк Zapełnienie bufora linii PCM - - - - + + + + Число сшивок полей, на которых не удалось проверить корректность сборки блоков данных Liczba kombinacji pól, które nie zostały zweryfikowane pod kątem poprawności złozonych bloków danych - + Непроверенных сшивок полей: Niesprawdzone kombinacje pól: - - - - + + + + Число блоков данных, в которых успешно исправлена одиночная ошибка Liczba bloków danych w których pojedyncze błędy próbek zostały naprawione - + Успешных P-коррекций: Udane korekcje P-kodu: - - - - + + + + Число блоков данных, в которых успешно исправлена двойная ошибка Liczba bloków danych w których podwójne błędy próbek zostały naprawione - + Успешных Q-коррекций: Udane korekcje Q-kodu: - - - - + + + + Число блоков данных, которые невозможно восстановить кодами P и Q Liczba bloków danych, które nie zostały naprawione przez P i Q-kody - + Неисправленных блоков данных: Zakłócenia bloku danych: - - + + Заполненность буфера PCM блоков данных Zapełnienie bufora bloku danych - - - - + + + + Формат кодирования PCM в исходном видео-файле - + Формат PCM: - + STC-007/Sony PCM-F1 STC-007/PCM-F1 @@ -664,55 +720,55 @@ bloku danych: - - - - + + + + Разрешение декодируемого аудио (будет приведено к 16 битам на выходе) - - - - - - - - + + + + + + + + Частота отсчётов декодируемого аудио (будет записана в заголовок WAV) - - + + Частота отсчётов: - - + + 44056 Гц - - + + 44100 Гц - + SI-формат - + EI-формат - + Режим PCM-1630: @@ -722,433 +778,466 @@ bloku danych: - - Вставка сверху: - - - - - Вставка снизу: - - - - - - - + + + + Режим кодирования PCM-1630 - - - - + + + + Разрешение исправления ошибок CRC кодами коррекции - + включена (P-код) - + полная (P и Q коды) - + частичная (P-код) - - + + Активация дополнительной коррекции Cross-Word Decoding - + CWD коррекция - + CWD отключено - + заглушать по отсчётам - + PCM-1 (Sony Standard B) PCM-1 (Standard B) - + PCM-16x0 (Sony Standard A) PCM-16x0 (Standard A) - - - - + + Применение коррекции АЧХ - + Деэмфазис: - + + + Функционал ещё не готов + + + + включён - + отключён - + Параметры сборки кадра PCM-1 - - - - - - + + + + + + Количество строк, в которых могут быть PCM-данные - - - + + + Строк данных: - - - - + + + + Количество строк, которое необходимо вставить выше PCM-данных в нечётном поле - - - - + + + + Количество строк, которое необходимо вставить выше PCM-данных для корректной сборки кадра - - + + Дополнение сверху: - - - - + + + + Количество строк, которое необходимо вставить ниже PCM-данных в нечётном поле - - - - + + + + Количество строк, которое необходимо вставить ниже PCM-данных для корректной сборки кадра - - + + Дополнение снизу: - - - - - - - - - - - - + + + + + + + + + + + + Установленный порядок полей в кадре - - - - - - - - - - - - + + + + + + + + + + + + Номер кадра исходного видео, для которого применяются параметры сборки - - - + + + Номер кадра: - - - - + + + + Количество строк, которое необходимо вставить выше PCM-данных в чётном поле - - - - + + + + Количество строк, которое необходимо вставить ниже PCM-данных в чётном поле - - - - - - + + + + + + Количество строк PCM-данных в нечётном поле - - - - - - + + + + + + Количество строк PCM-данных в чётном поле - - - + + + + + + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + + + + + + Координаты: - + + + + + + + Усреднённые по кадру координаты начала данных (в пикселях) + + + + + + + + + + Усреднённые по кадру координаты конца данных (в пикселях) + + + + Параметры сборки кадра PCM-1600/PCM-1610/PCM-1630 - - - - + + + + Формат данных PCM-1630 - + Формат данных: - + Параметры сборки кадра STC-007/PCM-F1 - - + + Установленное разрешение аудио - - + + Вставка строк между PCM-данными из полей одного кадра - + Количество строк, которое необходимо вставить между PCM-данными соседних полей для корректной сборки кадра - - + + Вставка строк между PCM-данными из смежных полей соседних кадров - - - - + + + + Общее число кадров в источнике - + Всего кадров: - - - - + + + + Число блоков данных, не имеющих ошибок по CRC, но не прошедшие проверку по P и Q словам - + "Сломанных" блоков данных: - - - - + + + + + Число блоков данных, в которых успешно исправлены ошибки с помощью Cross-Word Decoding + + + + + Успешных +CWD-коррекций: + + + + + + + Число аудио-отсчётов, которые невозможно восстановить кодами P и Q - + Неисправленных аудио-отсчётов: - - - - + + + + Число аудио-отсчётов, в которых замаскировано выпадение Liczba próbek dźwięku, które zostały zamaskowane - + Маскировано аудио-отсчётов: Zamaskowane zakłócenia: - - - - Число аудио-отсчётов, в которых заглушено выпадение - Liczba wyciszonych zakłóceń próbek dźwięku + Liczba wyciszonych zakłóceń próbek dźwięku - Заглушено аудио-отсчётов: - Wyciszone + Wyciszone zakłócenia: - + Отладка: время выполнения Debugowanie: czas działania - + Файл Plik - + Отладка Debugowanie - - - - - - - - - - + + + + + + + + + + Вывод отладочной информации в консоль Kieruj informacje debugowania do konsoli - + Сырые данные при бинаризации - + Сбросить настройки декодирования в главном окне - + Отключиться от захвата - + Захватить PCM с видео захвата... - + Захват видео с устройства для декодирования PCM - + Закрыть источник - + Отключиться от выбранного источника видео - + Координаты данных @@ -1161,124 +1250,124 @@ zakłócenia: Binaryzacja - + Деинтерливинг, пересборка кадров Rozplatanie i ponowne składanie klatek - + Общее Ogólne - - + + Запуск фоновых процессов тестирования внутренних вычислений Uruchom w tle testy wewnętrznych obliczeń i logiki - + Вычислительные тесты Testy obliczeniowe - + Обработка и вывод аудио Przetwarzanie dźwięku i wyjście - + Настройки Ustawienia - - + + Выбор языка интерфейса Wybierz język interfejsu - + Язык интерфейса Język interfejsu - + Визуализация - + Справка - + Это строка состояния, здесь выводятся подсказки To jest pasek stanu ze wskazówkami pomocy - + Открыть видео с PCM... Otwórz plik wideo z PCM... - + Открытие видео-файла поддерживаемого формата, содержащего PCM - + Диалог открытия файла изображения, содержащего PCM Диалог открытия видео-файла поддерживаемого формата, содержащего PCM Otwórz okno wyboru pliku wideo z PCM - + Открыть изображение с PCM... Otwórz plik obrazu z PCM... - + Захват и декодирование видео - + Поиск данных, бинаризация - + Выход Zakończ - + Закрыть приложение Zamknij aplikację - + Данные по кадрам Dane klatki - + Данные по строкам Dane linii - + Данные по пикселям Dane pikseli - - - - - + + + + + Общий процесс Ogólny proces @@ -1287,175 +1376,175 @@ zakłócenia: Współrzędne pikseli, dane surowe - + Статистика распределения яркостей Statystyki poziomów luminacji - + Полный процесс подбора порога бинаризации Proces przeszukiwania progowego binaryzacji - + Выключить весь вывод отладки Wyłącz wszystkie wyjścia debugowania - + Отключить вывод всей отладки в консоль Wyłącz wszystkie wyjścia debugowania na konsoli - + Дампы обработанных PCM-строк Zrzut przetworzonych linii PCM - + Дампы обработанных блоков данных Zrzut przetworzonych bloków danych PCM - - - - - + + + + + Ввод настроек Zmiany ustawień - - - - - + + + + + Выключить все Wyłącz wszystkie powyższe - + Дамп полей при подборе вставки Zrzut pola podczas detekcji pustych linii - + Дамп блоков данных при подборе вставки Zrzut bloku danych podczas detekcji pustych linii - + Подбор вставок для полей кадра Wykrywanie pustych linii pomiędzy polami - + Определение границ PCM в кадре Przycinanie klatki - + Преобразование строк в блоки данных PCM-lines to data blocks conversion - + Проверить подсчёт CRCC Sprawdź obliczanie CRCC - + Проверить работу ECC STC-007 (корректора ошибок) Sprawdź obliczanie ECC - + Операции глушения и маскирования Operacje maskowania i wyciszania - + Дамп буфера аудио Zrzut bufora próbek audio - + Сохранение в файл Zapisywanie do pliku - + Пересборка кадров со вставками Ponowne składanie klatek z pustymi liniami - + Исправление ошибок по P и Q кодам Korekcja błędów P i Q-kodem - + Вывод аудио в звуковой интерфейс Wyjście audio w czasie rzeczywistym - + Тонкие настройки бинаризатора... - + Открыть диалог тонкой настройки бинаризатора - + Тонкие настройки деинтерливера... - + Открыть диалог тонкой настройки деинтерливера - + Тонкие настройки видео-декодера... - + Открыть диалог тонкой настройки видео-декодера - + О программе... - + Открытие окна с информацией о программе - + Сбросить все настройки - + Сбросить все настройки приложения (включая последнюю папку и положения окон) - + Сбросить положения окон - + Сбросить настройки декодера @@ -1464,106 +1553,106 @@ zakłócenia: Otwórz okno ustawień - + Источник видео - + Бинаризированные кадры - + Пересобранные кадры - + Блоки данных - - - + + + Ошибка Błąd - + Открыть видео с PCM Otwórz wideo z PCM - + Видео-файлы (*.avi *.mkv *.mpg *.mp4) Pliki wideo (*.avi *.mkv *.mpg *.mp4) - - + + Сброс настроек Resetowanie ustawień - + Сброс настроек декодера - + Вернуть настройки к состоянию по умолчанию? Przywrócić ustawienia domyślne? - + Сброс расположения - + Сброс расположения окон визуализации - + Сбросить положения окон визуализации? - + Сброс ВСЕХ настроек - + Вернуть ВСЕ настройки программы к состоянию по умолчанию? - - + + Результат Rezultat - + Тест CRCC пройден успешно. Test CRCC zakończony pomyślnie. - + Тест CRCC не пройден! Подробности в отладочной консоли. Test CRCC nieudany! Szczegóły w konsoli debugowania. - + Тест ECC пройден успешно. Test ECC zakończony pomyślnie. - + Тест ECC не пройден! Подробности в отладочной консоли. Test ECC nieudany! Szczegóły w konsoli debugowania. @@ -1571,98 +1660,98 @@ zakłócenia: QObject - - + + не определён nie określono - + TFF, нечётное поле первое TFF, najpierw górne pole - + BFF, чётное поле первое BFF, najpierw dolne pole - + (форсировано) - + NTSC (525i), 245 строк с PCM в поле NTSC (525i), 245 linii PCM na pole - + PAL (625i), 294 строк с PCM в поле PAL (625i), 294 linii PCM na pole - + Формат SI - + Формат EI - + (форсирован) - + 14 бит (STC-007) 14 bit (STC-007) - + 14 бит (неточно) 14 bit (nie określono) - + 16 бит (неточно) 16 bit (nie określono) - + 16 бит (PCM-F1) 16 bit (PCM F-1) - + Источник видео - + Бинаризированные кадры - + Пересобранные кадры - + Блоки данных - + Для использования меню отладки запустите приложение из коммандной строки Aby skorzystać z menu debugowania, uruchom aplikację za pomocą wiersza poleceń - + Кадр: @@ -1682,80 +1771,112 @@ zakłócenia: + + SamplesToWAV + + + Вывод в WAV: не удалось открыть на запись файл ' + + + + + Вывод в WAV: не удалось добавить заголовок, файл не открыт! + + + + + Вывод в WAV: не удалось добавить заголовок в файл! + + + + + + + + + Вывод в WAV: не удалось обновить заголовок в файле! + + + + + Вывод в WAV: не удалось записать аудио данные в файл! + + + VideoInFFMPEG - + Указанный файл источника не найден! - + Недостаточно прав для чтения файла источника! - + FFMPEG: Не удалось открыть файл - + FFMPEG: Не удалось получить информацию о потоке видео - + FFMPEG: Не удалось найти поток видео - + FFMPEG: Не удалось найти декодер для видео - + FFMPEG: Не удалось выделить ОЗУ для декодера видео - + FFMPEG: Не удалось установить параметры для декодера видео - + FFMPEG: Не удалось запустить декодер видео - + FFMPEG: Не удалось выделить ОЗУ для буфера кадра - + FFMPEG: Не удалось считать пакет данных из декодера - + FFMPEG: Не удалось инициализировать преобразователь кадра - + FFMPEG: Не удалось преобразовать формат кадра видео - + FFMPEG: Не задан источник видео - + FFMPEG: Неизвестная ошибка чтения видео @@ -1775,8 +1896,8 @@ zakłócenia: - <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> - <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, STANDARD B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, STANDARD A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> + <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, Sony PCM-F1, NTSC/PAL)</p></body></html> + <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> @@ -1829,189 +1950,309 @@ zakłócenia: + + Разрешение захватываемого изображения + + + + Разрешение: - - - - + + + Смещение левого верхнего угла конечного кадра по горизонтали + + + + + + + пикс. - + + + Горизонтальное разрешение захватываемого изображения + + + + + + + + Частота кадров в секунду для захвата + + + + кадр/сек - + + + Установить параметры захвата для PAL видео + + + + + + + + Параметры, с которыми производится захват (могут отличаться от заданных из-за ограничений устройства захвата) + + + + Применено: - + + + Установить параметры захвата по видео стандарту + + + + Предустановка: - + Частота кадров: - + + + Смещение левого верхнего угла конечного кадра от кадра источника + + + + Смещение: - + + + Установить параметры захвата для NTSC видео + + + + + + Вертикальное разрешение захватываемого изображения + + + + + + Смещение левого верхнего угла конечного кадра по вертикали + + + + + + Применить настройки выше для текущего выбранного устройства + + + + Применить - + + + Оставить настройки захвата по умолчанию + + + + Настройки устройства по умолчанию - + + + + + Используемый для захвата изображения цветовой канал + + + + Яркость (канал Y) - + Красный (канал R) - + Зелёный (канал G) - + Синий (канал B) - + Цветовой канал: - + Доступные устройства захвата видео - + + + Список доступных в системе устройств захвата видео + + + + + + Запросить актуальный список устройств захвата + + + + Обновить список - + Предпросмотр (чёрно-белый) - + + + Предпросмотр устройства захвата в реальном времени + + + + + + Функционал ещё не готов + + + + Сохранить Zapisz - + + + Закрыть окно без сохранения изменений + + + + Закрыть Zamknij - + Список обновляется... - + Ошибка Błąd - + Не получен вовремя ответ от FFMPEG, возможно библиотека зависла. - + Нет устройств захвата видео - + Устройство не выбрано - + FFMPEG: Не удалось открыть захват с заданными параметрами - + FFMPEG: Не удалось получить информацию о потоке видео - + FFMPEG: Не удалось найти поток видео - + FFMPEG: Не удалось найти декодер для видео - + FFMPEG: Не удалось выделить ОЗУ для декодера видео - + FFMPEG: Не удалось установить параметры для декодера видео - + FFMPEG: Не удалось запустить декодер видео - + FFMPEG: Не удалось выделить ОЗУ для буфера кадра - + FFMPEG: Не удалось считать пакет данных из декодера - + FFMPEG: Не удалось инициализировать преобразователь кадра - + FFMPEG: Не удалось преобразовать формат кадра видео - + FFMPEG: Неизвестная ошибка захвата видео - + Ошибка захвата видео diff --git a/about_wnd.ui b/about_wnd.ui index d293d02..9dbcfeb 100644 --- a/about_wnd.ui +++ b/about_wnd.ui @@ -58,7 +58,7 @@ true - <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC/PAL)</p></body></html> + <html><head/><body><p>+ <span style=" font-weight:600;">PCM-1</span> (2 канала, 13 бит, 44056 Гц, Sony Standard B, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1600</span> (2 канала, 16 бит, 44056 Гц, Sony Standard A, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1610</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">PCM-1630</span> (2 канала, 16 бит, 44056/44100 Гц, NTSC)<br/>+ <span style=" font-weight:600;">STC-007</span> (2 канала, 14 бит, 44056 Гц, EIAJ NTSC)<br/>+ <span style=" font-weight:600;">STC-008</span> (2 канала, 14 бит, 44100 Гц, EIAJ PAL)<br/>+ <span style=" font-weight:600;">PCM-F1</span> (2 канала, 16 бит, 44056/44100 Гц, Sony PCM-F1, NTSC/PAL)</p></body></html> diff --git a/audioprocessor.cpp b/audioprocessor.cpp index 2817856..b762fa5 100644 --- a/audioprocessor.cpp +++ b/audioprocessor.cpp @@ -6,15 +6,14 @@ AudioProcessor::AudioProcessor(QObject *parent) : QObject(parent) { - file_path.clear(); - file_name.clear(); in_samples = NULL; mtx_samples = NULL; - tim_outflush = NULL; + tim_outflush = tim_vu_fade = NULL; prebuffer.clear(); for(uint8_t idx=0;idx *in_samplepairs, { if((in_samplepairs==NULL)||(mtx_samplepairs==NULL)) { - qWarning()<317000) + { + log_level |= LOG_DROP_ACT|LOG_BUF_DUMP; + }*/ } } // Unlock shared access. @@ -190,11 +196,11 @@ bool AudioProcessor::fillUntilBufferFull() { qInfo()<<"[AP] Added"< *samples, Coordinat for(int16_t queue_idx=range.data_start;queue_idx<=range.data_stop;queue_idx++) { // Mark as fixed. - (*samples)[queue_idx].setFixed(); + (*samples)[queue_idx].setValid(); mark_cnt++; } #ifdef AP_EN_DBG_OUT @@ -493,8 +499,24 @@ uint16_t AudioProcessor::clearInvalids(std::deque *samples, Coordinat return mark_cnt; } -//------------------------ Perform zeroing out on all dropouts in the provided range. -uint16_t AudioProcessor::performMute(std::deque *samples, CoordinatePair &range) +//------------------------ Perform zeroing out on a sample, pointet by [offset]. +uint16_t AudioProcessor::sampleMute(std::deque *samples, int16_t offset) +{ + // Check if provided coordinate fit inside the buffer. + if((offset<0)||(offset>(uint16_t)(samples->size()-1))) + { + qWarning()<size()< *samples, CoordinatePair &range) { uint16_t mask_cnt; @@ -504,7 +526,7 @@ uint16_t AudioProcessor::performMute(std::deque *samples, CoordinateP // Check if provided coordinates fit inside the buffer. if((range.data_start<0)||(range.data_stop>=(int16_t)samples->size())) { - qWarning()<size(); + qWarning()<size()< *samples, CoordinateP // Mute and mark as processed only if the value differs. mask_cnt++; (*samples)[queue_idx].setValue(SMP_NULL); - (*samples)[queue_idx].setProcessed(); + (*samples)[queue_idx].setMasked(); } // Mark as fixed. - (*samples)[queue_idx].setFixed(); + (*samples)[queue_idx].setValid(); } #ifdef AP_EN_DBG_OUT if((log_level&LOG_DROP_ACT)!=0) @@ -548,13 +570,13 @@ uint16_t AudioProcessor::performMute(std::deque *samples, CoordinateP } else { - qWarning()<size()< *samples, CoordinatePair &range) +uint16_t AudioProcessor::rangeLevelHold(std::deque *samples, CoordinatePair &range) { uint16_t mask_cnt; int16_t hold_word; @@ -565,7 +587,7 @@ uint16_t AudioProcessor::performLevelHold(std::deque *samples, Coordi // Check if provided coordinates fit inside the buffer. if((range.data_start<0)||(range.data_stop>=(int16_t)samples->size())) { - qWarning()<size(); + qWarning()<size()< *samples, Coordi // Hold the same starting level and mark as processed only if the value differs. mask_cnt++; (*samples)[queue_idx].setValue(hold_word); - (*samples)[queue_idx].setProcessed(); + (*samples)[queue_idx].setMasked(); } // Mark as fixed. - (*samples)[queue_idx].setFixed(); + (*samples)[queue_idx].setValid(); } #ifdef AP_EN_DBG_OUT if((log_level&LOG_DROP_ACT)!=0) @@ -612,13 +634,13 @@ uint16_t AudioProcessor::performLevelHold(std::deque *samples, Coordi } else { - qWarning()<size()< *samples, CoordinatePair &range) +uint16_t AudioProcessor::rangeLinearInterpolation(std::deque *samples, CoordinatePair &range) { bool same_level; uint16_t mask_cnt, int_idx; @@ -633,7 +655,7 @@ uint16_t AudioProcessor::performLinearInterpolation(std::deque *sampl // Check if provided coordinates fit inside the buffer. if((range.data_start<0)||(range.data_stop>=(int16_t)samples->size())) { - qWarning()<size(); + qWarning()<size()< *sampl // Interpolate and mark as processed only if the value differs. mask_cnt++; (*samples)[queue_idx].setValue((int16_t)lvl_delta); - (*samples)[queue_idx].setProcessed(); + (*samples)[queue_idx].setMasked(); } // Mark as fixed. - (*samples)[queue_idx].setFixed(); + (*samples)[queue_idx].setValid(); int_idx++; } #ifdef AP_EN_DBG_OUT @@ -717,7 +739,7 @@ uint16_t AudioProcessor::performLinearInterpolation(std::deque *sampl } else { - qWarning()<size()< *samples) { bool suppress_log; bool good_after_bad, good_before_bad, bad_lock; - int16_t leftover; + int16_t leftover, bad_stop, good_at_the_end, good_end; uint16_t masks_cnt; - size_t queue_size, queue_idx, bad_stop, good_at_the_end, good_end; + size_t queue_size, queue_idx; std::deque bad_regions; #ifdef AP_EN_DBG_OUT @@ -778,7 +800,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) // Invalid samples were not found before. // Save and lock bad position. bad_lock = true; - bad_stop = queue_idx; + bad_stop = (int16_t)queue_idx; #ifdef AP_EN_DBG_OUT if(suppress_log==false) { @@ -797,7 +819,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) // Invalid samples were not detected yet, // every sample from the end of the buffer is still valid. // Update last location with valid samples. - good_at_the_end = queue_idx; + good_at_the_end = (int16_t)queue_idx; #ifdef AP_EN_DBG_OUT if(suppress_log==false) { @@ -817,7 +839,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) // Some invalid samples were found towards the end of the buffer, // maybe an invalid region is found. // Save position of valid samples before invalid ones. - good_end = queue_idx; + good_end = (int16_t)queue_idx; #ifdef AP_EN_DBG_OUT if(suppress_log==false) { @@ -835,7 +857,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) { // No valid samples found after this one and found some invalid samples. // Check how far from the end of the buffer valid data ends. - if(good_end>=(samples->size()-(max_ramp_down+max_ramp_up+1))) + if(good_end>=((int16_t)samples->size()-(int16_t)(max_ramp_down+max_ramp_up+1))) { // Not enough invalid samples to choose between one region // or two ramps and silent region. @@ -856,9 +878,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) // Calculating ending coordinate for the ramp-down. new_region.data_stop = new_region.data_start+max_ramp_down+1; // Force last sample of the ramp to valid zero. - (*samples)[new_region.data_stop].setFixed(); - (*samples)[new_region.data_stop].setProcessed(); - (*samples)[new_region.data_stop].setValue(SMP_NULL); + sampleMute(samples, new_region.data_stop); // Ramp-down region will be added to the list at the end. #ifdef AP_EN_DBG_OUT if(suppress_log==false) @@ -904,7 +924,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) } #endif // Check if starting sample was processed earlier. - if(((*samples)[new_region.data_start].isProcessed()==false)|| + if(((*samples)[new_region.data_start].isMasked()==false)|| ((*samples)[new_region.data_start].audio_word!=SMP_NULL)) { // Starting sample was not altered - it was valid from the source. @@ -932,9 +952,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) new_region.data_start = new_region.data_stop-max_ramp_up-1; bad_regions.push_front(new_region); // Force first sample of the ramp-up (last sample of muted region) to zero. - (*samples)[new_region.data_start].setFixed(); - (*samples)[new_region.data_start].setProcessed(); - (*samples)[new_region.data_start].setValue(SMP_NULL); + sampleMute(samples, new_region.data_start); #ifdef AP_EN_DBG_OUT if(suppress_log==false) { @@ -955,9 +973,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) { bad_regions.push_front(new_region); // Force last sample of the ramp-down (first sample of muted region) to zero. - (*samples)[new_region.data_start].setFixed(); - (*samples)[new_region.data_start].setProcessed(); - (*samples)[new_region.data_start].setValue(SMP_NULL); + sampleMute(samples, new_region.data_start); #ifdef AP_EN_DBG_OUT if(suppress_log==false) { @@ -1013,9 +1029,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) new_region.data_start = new_region.data_stop-max_ramp_up-1; bad_regions.push_front(new_region); // Force first sample of the ramp-up (last sample of muted region) to zero. - (*samples)[new_region.data_start].setFixed(); - (*samples)[new_region.data_start].setProcessed(); - (*samples)[new_region.data_start].setValue(SMP_NULL); + sampleMute(samples, new_region.data_start); #ifdef AP_EN_DBG_OUT if(suppress_log==false) { @@ -1063,7 +1077,7 @@ void AudioProcessor::fixBadSamples(std::deque *samples) good_after_bad = true; bad_lock = false; // Update last location with valid samples. - good_at_the_end = queue_idx; + good_at_the_end = (int16_t)queue_idx; } } if(queue_idx==0) break; @@ -1095,17 +1109,17 @@ void AudioProcessor::fixBadSamples(std::deque *samples) if((mask_mode==DROP_MUTE_BLOCK)||(mask_mode==DROP_MUTE_WORD)) { // Mute dropouts. - masks_cnt += performMute(samples, *buf_scaner); + masks_cnt += rangeMute(samples, *buf_scaner); } else if((mask_mode==DROP_HOLD_BLOCK)||(mask_mode==DROP_HOLD_WORD)) { // Hold last valid level on dropouts. - masks_cnt += performLevelHold(samples, *buf_scaner); + masks_cnt += rangeLevelHold(samples, *buf_scaner); } else if((mask_mode==DROP_INTER_LIN_BLOCK)||(mask_mode==DROP_INTER_LIN_WORD)) { // Perform linear interpolation on dropouts. - masks_cnt += performLinearInterpolation(samples, *buf_scaner); + masks_cnt += rangeLinearInterpolation(samples, *buf_scaner); } buf_scaner++; } @@ -1153,14 +1167,15 @@ void AudioProcessor::fixBadSamples(std::deque *samples) new_region.data_start, new_region.data_stop, (uint32_t)(*samples)[new_region.data_start].getIndex(), (uint32_t)(*samples)[new_region.data_stop].getIndex()); qInfo()<samples[PCMSamplePair::CH_LEFT].getAmplitude(); + // Convert to logarithmic scale 8-bit level. + amp_left = sample2vu[amp_left]; + // Do the same for the right channel. + amp_right = in_samples->samples[PCMSamplePair::CH_RIGHT].getAmplitude(); + amp_right = sample2vu[amp_right]; + // Make current VU meters levels not less than current level from samples. + if(vu_left<(uint8_t)amp_left) + { + vu_left = (uint8_t)amp_left; + } + if(vu_right<(uint8_t)amp_right) + { + vu_right = (uint8_t)amp_right; + } + } +} + //------------------------ Write an element to the outputs. void AudioProcessor::outputWordPair(PCMSamplePair *out_samples) { @@ -1241,6 +1286,7 @@ void AudioProcessor::outputWordPair(PCMSamplePair *out_samples) { sc_output.saveAudio(*out_samples); } + samplesToVU(out_samples); emit outSamples(*out_samples); } @@ -1251,7 +1297,7 @@ void AudioProcessor::outputAudio() uint16_t points_done, lim_play, lim_cutoff; PCMSamplePair data_point; - lim_play = lim_cutoff = 0; + lim_play = lim_cutoff = min_valid_before; if(file_end==false) { // If not EOF yet - leave some data in the buffer for look-ahead. @@ -1270,7 +1316,7 @@ void AudioProcessor::outputAudio() // Dump processed audio until minimum look-ahead number of data points left in the buffer. while(prebuffer.size()>min_valid_before) { - // Make sure that first sample in the queue will remain valid. + // Make sure that first samples in the queue will remain valid. for(uint8_t idx=0;idx<=min_valid_before;idx++) { stop_output = stop_output||(prebuffer.at(idx).isReadyForOutput()==false); @@ -1327,7 +1373,7 @@ bool AudioProcessor::scanBuffer() { scan_limit = prebuffer.size()-min_valid_before-max_ramp_down-max_ramp_up; } - if((unprocessed!=false)&&(prebuffer.size()>scan_limit)) + if(prebuffer.size()>scan_limit) { // Split prebuffer into per-channel buffers. splitPerChannel(); @@ -1371,12 +1417,6 @@ bool AudioProcessor::scanBuffer() } // TODO: perform de-emphasis if required. } - // Re-fill prebuffer from per-channel buffers. - fillBufferForOutput(); - // Output from the buffer until half of it is empty. - outputAudio(); - unprocessed = false; - return true; } else @@ -1408,8 +1448,14 @@ void AudioProcessor::restartFlushTimer() tim_outflush->start(); } +//------------------------ Receive error message and redirect it. +void AudioProcessor::redirectError(QString in_err) +{ + emit mediaError(in_err); +} + //------------------------ Close output by timeout. -void AudioProcessor::actCloseOutput() +void AudioProcessor::actFlushOutput() { #ifdef AP_EN_DBG_OUT if((log_level&LOG_PROCESS)!=0) @@ -1421,12 +1467,44 @@ void AudioProcessor::actCloseOutput() tim_outflush->stop(); } -//------------------------ Reacting on live playback state. +//------------------------ Emit [guiLivePB] signal to report live playback state. void AudioProcessor::livePlayUpdate(bool flag) { emit guiLivePB(flag); } +//------------------------ Timer event for VU-meters updating and fading. +void AudioProcessor::updateVUMeters() +{ + // Report VU meters values. + if(out_to_live==false) + { + // Don't show levels if live playback is not enabled. + vu_left = vu_right = 0; + } + else + { + // Fade meters down. + if(vu_left>6) + { + vu_left -= 6; + } + else if(vu_left>0) + { + vu_left--; + } + if(vu_right>6) + { + vu_right -= 6; + } + else if(vu_right>0) + { + vu_right--; + } + } + emit outVULevels(vu_left, vu_right); +} + //------------------------ Set logging level. void AudioProcessor::setLogLevel(uint8_t new_log) { @@ -1442,7 +1520,6 @@ void AudioProcessor::setFolder(QString in_path) qInfo()<<"[AP] Target folder set to"<start(); // Inf. loop in a thread. while(finish_work==false) @@ -1614,11 +1697,20 @@ void AudioProcessor::processAudio() { // No new data has been added. // Calm down. - QThread::msleep(100); + QThread::msleep(50); + } + else + { + // Process data in the internal buffer. + if(scanBuffer()!=false) + { + // Re-fill prebuffer from per-channel buffers. + fillBufferForOutput(); + // Output from the internal buffer. + outputAudio(); + unprocessed = false; + } } - - // Process data in the internal buffer. - scanBuffer(); file_end = false; } @@ -1654,7 +1746,7 @@ void AudioProcessor::purgePipeline() channel_bufs[idx].clear(); long_bads[idx].clear(); } - empty_smp.setSamplePair(SMP_NULL, SMP_NULL, true, true, true, true); + empty_smp.setSamplePair(SMP_NULL, SMP_NULL, true, true, true, true, false, false); prebuffer.push_back(empty_smp); sample_index = 1; } diff --git a/audioprocessor.h b/audioprocessor.h index 2ca4fda..395d472 100644 --- a/audioprocessor.h +++ b/audioprocessor.h @@ -15,6 +15,7 @@ #include #include "config.h" #include "frametrimset.h" +#include "lookup.h" #include "pcmsamplepair.h" #include "samples2audio.h" #include "samples2wav.h" @@ -48,7 +49,7 @@ class AudioProcessor : public QObject MIN_LONG_INVALID = 16, // Minimum length of invalid region to be count as long. MAX_STRAY_LEN = 24, // Maximum length of valid region to be count as stray. MIN_VALID_BEFORE = 3, // Minimum number of valid data points to keep at the start of the buffer. - MAX_RAMP_DOWN = 128, // Length of ramp-down to mute region (in data points). + MAX_RAMP_DOWN = 192, // Length of ramp-down to mute region (in data points). MAX_RAMP_UP = 32, // Length of ramp-up from mute region (in data points). CHANNEL_CNT = PCMSamplePair::CH_MAX, // Number of channels for processing. }; @@ -75,21 +76,22 @@ class AudioProcessor : public QObject private: SamplesToAudio sc_output; // Handler for soundcard operations. SamplesToWAV wav_output; // Handler for WAV-file operations. - QString file_path; - QString file_name; std::deque *in_samples; // Input sample pair queue (shared). QMutex *mtx_samples; // Mutex for input queue. - QTimer *tim_outflush; + QTimer *tim_outflush; // Timer for dumping output from cache when input stalles. + QTimer *tim_vu_fade; // Timer for VU levels drop off. std::deque prebuffer; // Buffer for input data. std::deque channel_bufs[CHANNEL_CNT]; // Per-channel buffers for sample processing. - std::deque long_bads[CHANNEL_CNT]; + std::deque long_bads[CHANNEL_CNT]; // Per-channel buffers for regions of long invalid samples. uint8_t log_level; // Level of debug output. uint8_t mask_mode; // Mode of masking dropouts. - uint16_t min_valid_before; - uint16_t max_ramp_down; - uint16_t max_ramp_up; + uint16_t min_valid_before; // Minimum number of valid data points at the front of the buffer. + uint16_t max_ramp_down; // Length of ramp-down for interpolation from last valid sample into silence (inside invalid region). + uint16_t max_ramp_up; // Length of ramp-up for interpolation from silence (inside invalid region) into first valid sample. uint64_t sample_index; // Master index for samples for the current file. uint16_t sample_rate; // Last sample rate. + uint8_t vu_left; // VU-level for the left channel. + uint8_t vu_right; // VU-level for the right channel. bool file_end; // Detected end of a file. bool unprocessed; // Are there unprocessed audio samples? bool remove_stray; // Invalidate stray VALID samples. @@ -109,21 +111,25 @@ class AudioProcessor : public QObject uint16_t setInvalids(std::deque *samples, CoordinatePair &range); void fixStraySamples(std::deque *samples, std::deque *regions); uint16_t clearInvalids(std::deque *samples, CoordinatePair &range); - uint16_t performMute(std::deque *samples, CoordinatePair &range); - uint16_t performLevelHold(std::deque *samples, CoordinatePair &range); - uint16_t performLinearInterpolation(std::deque *samples, CoordinatePair &range); + uint16_t sampleMute(std::deque *samples, int16_t offset); + uint16_t rangeMute(std::deque *samples, CoordinatePair &range); + uint16_t rangeLevelHold(std::deque *samples, CoordinatePair &range); + uint16_t rangeLinearInterpolation(std::deque *samples, CoordinatePair &range); void fixBadSamples(std::deque *samples); void dumpPrebuffer(); void fillBufferForOutput(); + void samplesToVU(PCMSamplePair *in_samples); void outputWordPair(PCMSamplePair *out_samples); void outputAudio(); bool scanBuffer(); void dumpBuffer(); private slots: - void restartFlushTimer(); - void actCloseOutput(); + void restartFlushTimer(); // Stop and start flushing timer. + void redirectError(QString); // Receive error message and redirect it. + void actFlushOutput(); // Timer event for flushing buffer. void livePlayUpdate(bool); // Emit [guiLivePB] signal to report live playback state. + void updateVUMeters(); // Timer event for VU-meters updating and fading. public slots: void setLogLevel(uint8_t); // Set logging level. @@ -139,9 +145,11 @@ public slots: signals: void guiAddMask(uint16_t); // Report new masked samples. void guiLivePB(bool); // Report live playback state. + void mediaError(QString); // Error while processing audio. void newSource(); // Report about changed source. - void reqTimerRestart(); + void reqTimerRestart(); // Deffered call for [restartFlushTimer()]. void outSamples(PCMSamplePair); // Copy of outputting samples. + void outVULevels(uint8_t, uint8_t); // Report VU-meters. void stopOutput(); // Report about thread terminating. void finished(); }; diff --git a/binarizer.h b/binarizer.h index 66ffbc0..390b07e 100644 --- a/binarizer.h +++ b/binarizer.h @@ -9,9 +9,9 @@ * * This module takes one video line (of type [VideoLine]) and performs: * - AGC (Automatic Gain Control), statistically detecting BLACK and WHITE levels; -* - Automatic reference level detection, detecting the best threshold for binarization; +* - ARLD (Automatic Reference Level Detection), detecting the best threshold for binarization; * - TBC (Time-Based Correction), detecting horizontal offset of the PCM data in the line; -* - binarization with set mode; +* - Binarization with set mode; * - Brute force picking bits that were cut off the edge of the video line (for PCM-1 and PCM-16x0). * * Binarization itself can be done with different speed/quality ratios, diff --git a/capt_sel.cpp b/capt_sel.cpp index a9270ca..4b32ac3 100644 --- a/capt_sel.cpp +++ b/capt_sel.cpp @@ -13,6 +13,9 @@ capt_sel::capt_sel(QWidget *parent) : capt_dev = NULL; capture_rate = 100; + //ui->viewport->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); + ui->viewport->setOptimizationFlags(QGraphicsView::DontSavePainterState|QGraphicsView::DontAdjustForAntialiasing); + scene = new QGraphicsScene(this); ui->viewport->setScene(scene); ui->viewport->setAlignment(Qt::AlignLeft|Qt::AlignTop); @@ -42,7 +45,7 @@ capt_sel::capt_sel(QWidget *parent) : connect(capt_dev, SIGNAL(sigInputClosed()), this, SLOT(captureClosed())); connect(capt_dev, SIGNAL(sigVideoError(uint32_t)), this, SLOT(captureError(uint32_t))); connect(capt_dev, SIGNAL(newDeviceList(VCapList)), this, SLOT(refillDevList(VCapList))); - ffmpeg_thread->start(); + ffmpeg_thread->start(QThread::HighPriority); connect(ui->btnClose, SIGNAL(clicked(bool)), this, SLOT(usrClose())); connect(ui->btnSave, SIGNAL(clicked(bool)), this, SLOT(usrSave())); @@ -466,8 +469,10 @@ void capt_sel::redrawPreview(QImage in_image, bool in_double) return; } draw_rate = capt_meas.elapsed(); + // Check if this frame contains dropped frames counter. if(in_image.height()!=FFMPEGWrapper::DUMMY_HEIGTH) { + // It's normal frame for displaying. //qDebug()<<"[CSEL] New image"; // Update pixmap. pixels->setPixmap(QPixmap::fromImage(in_image.copy())); @@ -488,6 +493,7 @@ void capt_sel::redrawPreview(QImage in_image, bool in_double) } else { + // It's a dummy, containing dropped frames counter. qDebug()<<"[CSEL] New dummy image"; // Skip dummy frame and request next one. pollCapture(); diff --git a/capt_sel.ui b/capt_sel.ui index a36276c..9134c35 100644 --- a/capt_sel.ui +++ b/capt_sel.ui @@ -6,8 +6,8 @@ 0 0 - 1030 - 586 + 1017 + 588 @@ -38,6 +38,12 @@ 0 + + Разрешение захватываемого изображения + + + Разрешение захватываемого изображения + Разрешение: @@ -51,6 +57,12 @@ 0 + + Смещение левого верхнего угла конечного кадра по горизонтали + + + Смещение левого верхнего угла конечного кадра по горизонтали + пикс. @@ -70,6 +82,12 @@ 0 + + Горизонтальное разрешение захватываемого изображения + + + Горизонтальное разрешение захватываемого изображения + пикс. @@ -92,6 +110,12 @@ 0 + + Частота кадров в секунду для захвата + + + Частота кадров в секунду для захвата + кадр/сек @@ -114,6 +138,12 @@ 0 + + Установить параметры захвата для PAL видео + + + Установить параметры захвата для PAL видео + PAL @@ -127,6 +157,12 @@ 0 + + Параметры, с которыми производится захват (могут отличаться от заданных из-за ограничений устройства захвата) + + + Параметры, с которыми производится захват (могут отличаться от заданных из-за ограничений устройства захвата) + Применено: @@ -140,6 +176,12 @@ 0 + + Установить параметры захвата по видео стандарту + + + Установить параметры захвата по видео стандарту + Предустановка: @@ -162,6 +204,12 @@ Qt::NoFocus + + Параметры, с которыми производится захват (могут отличаться от заданных из-за ограничений устройства захвата) + + + Параметры, с которыми производится захват (могут отличаться от заданных из-за ограничений устройства захвата) + true @@ -175,6 +223,12 @@ 0 + + Частота кадров в секунду для захвата + + + Частота кадров в секунду для захвата + Частота кадров: @@ -188,6 +242,12 @@ 0 + + Смещение левого верхнего угла конечного кадра от кадра источника + + + Смещение левого верхнего угла конечного кадра от кадра источника + Смещение: @@ -201,6 +261,12 @@ 0 + + Установить параметры захвата для NTSC видео + + + Установить параметры захвата для NTSC видео + NTSC @@ -214,6 +280,12 @@ 0 + + Вертикальное разрешение захватываемого изображения + + + Вертикальное разрешение захватываемого изображения + пикс. @@ -236,6 +308,12 @@ 0 + + Смещение левого верхнего угла конечного кадра по вертикали + + + Смещение левого верхнего угла конечного кадра по вертикали + пикс. @@ -255,6 +333,12 @@ 0 + + Применить настройки выше для текущего выбранного устройства + + + Применить настройки выше для текущего выбранного устройства + Применить @@ -268,6 +352,12 @@ 0 + + Оставить настройки захвата по умолчанию + + + Оставить настройки захвата по умолчанию + Настройки устройства по умолчанию @@ -281,6 +371,12 @@ 0 + + Используемый для захвата изображения цветовой канал + + + Используемый для захвата изображения цветовой канал + Яркость (канал Y) @@ -311,6 +407,12 @@ 0 + + Используемый для захвата изображения цветовой канал + + + Используемый для захвата изображения цветовой канал + Цветовой канал: @@ -333,6 +435,12 @@ 0 + + Список доступных в системе устройств захвата видео + + + Список доступных в системе устройств захвата видео + QFrame::Panel @@ -346,6 +454,12 @@ 0 + + Запросить актуальный список устройств захвата + + + Запросить актуальный список устройств захвата + Обновить список @@ -385,6 +499,12 @@ Qt::NoFocus + + Предпросмотр устройства захвата в реальном времени + + + Предпросмотр устройства захвата в реальном времени + QFrame::Panel @@ -434,11 +554,17 @@ - + 0 0 + + Функционал ещё не готов + + + Функционал ещё не готов + Сохранить @@ -447,11 +573,17 @@ - + 0 0 + + Закрыть окно без сохранения изменений + + + Закрыть окно без сохранения изменений + Закрыть diff --git a/config.h b/config.h index 614f8fd..0d8f4e7 100644 --- a/config.h +++ b/config.h @@ -20,11 +20,11 @@ extern "C" #define DBG_QLINE QString::number(__LINE__, 10) #define DBG_ANCHOR QString("["+DBG_QFILE+": "+DBG_QFUNCTION+"(): #"+DBG_QLINE+"]") #define APP_ORG_NAME QString("Fagear") -#define APP_ORG_HTTP QString("http://fagear.ru") +#define APP_ORG_HTTP QString("https://discord.gg/4GcefbPffX") #define APP_NAME QString("Video PCM decoder") #define APP_NAME_LONG (QObject::tr("SDVPCM: декодер PCM аудио из SD видео")) #define APP_EXEC QString("SDVPCMdecoder") -#define APP_VERSION "0.99.5" +#define APP_VERSION "0.99.6" #define APP_INI_NAME QString("sdv2pcm") #define APP_LANG_PATH (qApp->applicationDirPath()) diff --git a/ffmpegwrapper.cpp b/ffmpegwrapper.cpp index d7b88db..637a28c 100644 --- a/ffmpegwrapper.cpp +++ b/ffmpegwrapper.cpp @@ -109,6 +109,14 @@ bool FFMPEGWrapper::getNextPacket() { emit sigVideoError(FFMERR_UNKNOWN); } +#ifdef FFWR_EN_DBG_OUT + if((av_res<0)&&(av_res!=AVERROR_EOF)) + { + char err_str[256]; + av_strerror(av_res, err_str, 256); + qWarning()<DUMMY_CNT_MAX) { + qWarning()<5 - 16 + 32 @@ -282,7 +282,7 @@ 5 - 32 + 64 diff --git a/frame_vis.cpp b/frame_vis.cpp index ed1a6e3..55a25a8 100644 --- a/frame_vis.cpp +++ b/frame_vis.cpp @@ -15,12 +15,19 @@ frame_vis::frame_vis(QWidget *parent) : prev_width = 640; prev_height = 480; + update_time.start(); + pos_timer.setSingleShot(true); pos_timer.setInterval(500); connect(&pos_timer, SIGNAL(timeout()), this, SLOT(updateWindowPosition())); scene = new QGraphicsScene(this); + ui->viewport->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); + //ui->viewport->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + ui->viewport->setOptimizationFlags(QGraphicsView::DontSavePainterState|QGraphicsView::DontAdjustForAntialiasing); + ui->viewport->setInteractive(false); + ui->viewport->setViewport(new QGLWidget(QGLFormat())); ui->viewport->setScene(scene); ui->viewport->setAlignment(Qt::AlignLeft|Qt::AlignTop); //ui->viewport->setCacheMode(QGraphicsView::CacheBackground); @@ -35,6 +42,8 @@ frame_vis::frame_vis(QWidget *parent) : pixels->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); scene->addItem(pixels); + connect(scene, SIGNAL(changed(QList)), this, SLOT(redrawDone())); + settings_hdl = new QSettings(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); if(settings_hdl!=NULL) { @@ -112,16 +121,22 @@ void frame_vis::setTitle(QString in_str) } //------------------------ Get new frame from renderer and display it. -void frame_vis::drawFrame(QPixmap in_pixmap, uint32_t in_frame_no) +void frame_vis::drawFrame(QImage in_img, uint32_t in_frame_no) { - if((prev_width!=in_pixmap.width())||(prev_height!=in_pixmap.height())) + if(in_img.isNull()!=false) { - qInfo()<<"[VIS] Resized to"<setPixmap(pix_data); - - scene->setSceneRect(0,0,prev_width,prev_height); + return; + } + if((prev_width!=in_img.width())||(prev_height!=in_img.height())) + { + qInfo()<<"[VIS] Resized to"<setPixmap(QPixmap::fromImage(in_img.copy())); + + scene->setSceneRect(0, 0, prev_width, prev_height); ui->viewport->setSceneRect(scene->sceneRect()); ui->viewport->adjustSize(); ui->viewport->viewport()->update(); @@ -132,10 +147,13 @@ void frame_vis::drawFrame(QPixmap in_pixmap, uint32_t in_frame_no) } else { - pixels->setPixmap(in_pixmap); + //pixels->setPixmap(QPixmap::fromImage(in_img.copy())); + pixels->setPixmap(QPixmap::fromImage(in_img)); ui->viewport->viewport()->update(); } + // Update frame number in the window title; this->setWindowTitle(win_title+QString::number(in_frame_no)); + update_time.start(); } //------------------------ Update window position and size in settings. @@ -153,3 +171,10 @@ void frame_vis::updateWindowPosition() } } } + +//------------------------ Scene redraw is done after last frame update. +void frame_vis::redrawDone() +{ + //qDebug()<<"[VIS] Preview updated"< #include #include +#include #include #include "config.h" #include "ui_frame_vis.h" @@ -44,6 +45,7 @@ class frame_vis : public QDialog private: Ui::frame_vis *ui; QTimer pos_timer; + QElapsedTimer update_time; QGraphicsScene *scene; QGraphicsPixmapItem *pixels; QPixmap pix_data; @@ -56,10 +58,14 @@ class frame_vis : public QDialog public slots: void setTitle(QString); - void drawFrame(QPixmap, uint32_t); + void drawFrame(QImage, uint32_t); private slots: void updateWindowPosition(); + void redrawDone(); + +signals: + void readyToDraw(); }; #endif // VISUALIZER_H diff --git a/frame_vis.ui b/frame_vis.ui index ad5fd07..6c7b807 100644 --- a/frame_vis.ui +++ b/frame_vis.ui @@ -32,8 +32,8 @@ false - - QLayout::SetMinimumSize + + 0 0 diff --git a/frametrimset.cpp b/frametrimset.cpp index f06cc73..01e88e2 100644 --- a/frametrimset.cpp +++ b/frametrimset.cpp @@ -769,6 +769,11 @@ FrameAsmSTC007::FrameAsmSTC007(const FrameAsmSTC007 &in_object) : FrameAsmDescri blocks_fix_p = in_object.blocks_fix_p; blocks_fix_q = in_object.blocks_fix_q; blocks_fix_cwd = in_object.blocks_fix_cwd; + ctrl_index = in_object.ctrl_index; + ctrl_hour = in_object.ctrl_hour; + ctrl_minute = in_object.ctrl_minute; + ctrl_second = in_object.ctrl_second; + ctrl_field = in_object.ctrl_field; } FrameAsmSTC007& FrameAsmSTC007::operator= (const FrameAsmSTC007 &in_object) @@ -797,6 +802,11 @@ FrameAsmSTC007& FrameAsmSTC007::operator= (const FrameAsmSTC007 &in_object) blocks_fix_p = in_object.blocks_fix_p; blocks_fix_q = in_object.blocks_fix_q; blocks_fix_cwd = in_object.blocks_fix_cwd; + ctrl_index = in_object.ctrl_index; + ctrl_hour = in_object.ctrl_hour; + ctrl_minute = in_object.ctrl_minute; + ctrl_second = in_object.ctrl_second; + ctrl_field = in_object.ctrl_field; return *this; } @@ -824,6 +834,7 @@ void FrameAsmSTC007::clearMisc() inner_padding_ok = outer_padding_ok = false; inner_silence = outer_silence = true; vid_std_preset = vid_std_guessed = false; + ctrl_index = ctrl_hour = ctrl_minute = ctrl_second = ctrl_field = 0; this->clearAsmStats(); } @@ -847,3 +858,9 @@ void FrameAsmSTC007::updateVidStdSoft(uint8_t in_std) } } } + +//------------------------ Is address data set from Control Block? +bool FrameAsmSTC007::isAddressSet() +{ + return ((ctrl_index!=0)||(ctrl_hour!=0)||(ctrl_minute!=0)||(ctrl_second!=0)||(ctrl_field!=0)); +} diff --git a/frametrimset.h b/frametrimset.h index bc2a6c2..e5fe5fb 100644 --- a/frametrimset.h +++ b/frametrimset.h @@ -229,6 +229,11 @@ class FrameAsmSTC007 : public FrameAsmDescriptor uint16_t blocks_fix_p; // Number of data blocks that were fixed with P-code. uint16_t blocks_fix_q; // Number of data blocks that were fixed with Q-code. uint16_t blocks_fix_cwd; // Number of data blocks that were fixed with help of CWD. + int8_t ctrl_index; // Index code from address word of Control Block. + int8_t ctrl_hour; // Hour (time code) from address word of Control Block. + int8_t ctrl_minute; // Minute (time code) from address word of Control Block. + int8_t ctrl_second; // Second (time code) from address word of Control Block. + int8_t ctrl_field; // Field code from address word of Control Block. public: FrameAsmSTC007(); @@ -238,5 +243,6 @@ class FrameAsmSTC007 : public FrameAsmDescriptor void clearMisc(); void clearAsmStats(); void updateVidStdSoft(uint8_t in_std); + bool isAddressSet(); }; #endif // FRAMETRIMSET_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 3081411..e996324 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -13,10 +13,6 @@ MainWindow::MainWindow(QWidget *parent) : L2B_PCM16X0_worker = NULL; L2B_STC007_worker = NULL; AP_worker = NULL; - captureSelectDialog = NULL; - vipFineSetDialog = NULL; - binFineSetDialog = NULL; - deintFineSetDialog = NULL; visuSource = NULL; visuBin = NULL; visuAssembled = NULL; @@ -30,7 +26,7 @@ MainWindow::MainWindow(QWidget *parent) : v_decoder_state = VDEC_IDLE; set_pcm_type = LIST_TYPE_PCM1; - lines_per_video = 0; + pcm1_ofs_diff = 0; stat_dbg_index = 0; for(uint8_t i=0;ithread()<<"ID"<start(QThread::LowestPriority); + input_FPU->start(QThread::HighPriority); connect(ui->mnLanguage, SIGNAL(triggered(QAction*)), this, SLOT(setLang(QAction*))); connect(ui->btnOpen, SIGNAL(clicked(bool)), this, SLOT(loadVideo())); connect(ui->actCloseSource, SIGNAL(triggered(bool)), this, SLOT(unloadSource())); - connect(ui->btnPlay, SIGNAL(clicked(bool)), this, SLOT(playVideo())); - connect(ui->btnPause, SIGNAL(clicked(bool)), this, SLOT(pauseVideo())); + connect(ui->btnPlay, SIGNAL(clicked(bool)), this, SLOT(usrPlayStop())); + connect(ui->btnPause, SIGNAL(clicked(bool)), this, SLOT(usrPause())); connect(ui->cbxLivePB, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); connect(ui->cbxWaveSave, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); - connect(ui->cbxFrameDropout, SIGNAL(toggled(bool)), this, SLOT(updateGUISettings())); - connect(ui->cbxLineDuplicate, SIGNAL(toggled(bool)), this, SLOT(updateGUISettings())); - connect(ui->cbxFrameStep, SIGNAL(toggled(bool)), this, SLOT(updateGUISettings())); + connect(ui->cbxFrameDropout, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); + connect(ui->cbxLineDuplicate, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); + connect(ui->cbxFrameStep, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); connect(ui->lbxBinQuality, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGUISettings())); connect(ui->lbxPCMType, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGUISettings())); connect(ui->lbxPCM1FieldOrder, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGUISettings())); + connect(ui->cbxPCM1Offset, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); + connect(ui->sldPCM1OddOfs, SIGNAL(valueChanged(int)), this, SLOT(updateGUISettings())); + connect(ui->sldPCM1EvenOfs, SIGNAL(valueChanged(int)), this, SLOT(updateGUISettings())); + connect(ui->btnPCM1OfsSync, SIGNAL(clicked(bool)), this, SLOT(updateGUISettings())); + connect(ui->sldPCM1OddOfs, SIGNAL(sliderMoved(int)), this, SLOT(sliderDisplayUpdate())); + connect(ui->sldPCM1EvenOfs, SIGNAL(sliderMoved(int)), this, SLOT(sliderDisplayUpdate())); + connect(ui->sldPCM1OddOfs, SIGNAL(valueChanged(int)), this, SLOT(sliderDisplayUpdate())); + connect(ui->sldPCM1EvenOfs, SIGNAL(valueChanged(int)), this, SLOT(sliderDisplayUpdate())); connect(ui->lbxPCM16x0Format, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGUISettings())); connect(ui->lbxPCM16x0FieldOrder, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGUISettings())); connect(ui->lbxPCM16x0ECC, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGUISettings())); @@ -205,7 +197,6 @@ MainWindow::MainWindow(QWidget *parent) : enableGUIEvents(); connect(ui->actLoadPCM, SIGNAL(triggered(bool)), this, SLOT(loadVideo())); - connect(ui->actLoadPicture, SIGNAL(triggered(bool)), this, SLOT(loadPicture())); connect(ui->actDecoderReset, SIGNAL(triggered(bool)), this, SLOT(resetOptDecoder())); connect(ui->actWinPosReset, SIGNAL(triggered(bool)), this, SLOT(resetVisPositions())); connect(ui->actFullReset, SIGNAL(triggered(bool)), this, SLOT(resetFull())); @@ -305,10 +296,13 @@ MainWindow::MainWindow(QWidget *parent) : connect(this, SIGNAL(aboutToExit()), L2B_PCM1_worker, SLOT(stop())); connect(this, SIGNAL(newL2BLogLevel(uint16_t)), L2B_PCM1_worker, SLOT(setLogLevel(uint16_t))); connect(this, SIGNAL(newPCM1FieldOrder(uint8_t)), L2B_PCM1_worker, SLOT(setFieldOrder(uint8_t))); + connect(this, SIGNAL(newPCM1AutoOffset(bool)), L2B_PCM1_worker, SLOT(setAutoLineOffset(bool))); + connect(this, SIGNAL(newPCM1OddOffset(int8_t)), L2B_PCM1_worker, SLOT(setOddLineOffset(int8_t))); + connect(this, SIGNAL(newPCM1EvenOffset(int8_t)), L2B_PCM1_worker, SLOT(setEvenLineOffset(int8_t))); connect(L2B_PCM1_worker, SIGNAL(newLineProcessed(PCM1SubLine)), this, SLOT(receiveAsmLine(PCM1SubLine))); connect(L2B_PCM1_worker, SIGNAL(newBlockProcessed(PCM1DataBlock)), this, SLOT(receivePCMDataBlock(PCM1DataBlock))); connect(L2B_PCM1_worker, SIGNAL(guiUpdFrameAsm(FrameAsmPCM1)), this, SLOT(updateStatsFrameAsm(FrameAsmPCM1))); - connect(L2B_PCM1_worker, SIGNAL(loopTime(quint64)), this, SLOT(updateDebugBar(quint64))); + //connect(L2B_PCM1_worker, SIGNAL(loopTime(quint64)), this, SLOT(updateDebugBar(quint64))); // Create and link PCM-16x0 deinterleaver worker. conv_L2B_PCM16X0 = NULL; @@ -331,7 +325,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(L2B_PCM16X0_worker, SIGNAL(newLineProcessed(PCM16X0SubLine)), this, SLOT(receiveAsmLine(PCM16X0SubLine))); connect(L2B_PCM16X0_worker, SIGNAL(newBlockProcessed(PCM16X0DataBlock)), this, SLOT(receivePCMDataBlock(PCM16X0DataBlock))); connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFrameAsm(FrameAsmPCM16x0)), this, SLOT(updateStatsFrameAsm(FrameAsmPCM16x0))); - connect(L2B_PCM16X0_worker, SIGNAL(loopTime(quint64)), this, SLOT(updateDebugBar(quint64))); + //connect(L2B_PCM16X0_worker, SIGNAL(loopTime(quint64)), this, SLOT(updateDebugBar(quint64))); // Create and link STC-007 deinterleaver worker. conv_L2B_STC007 = NULL; @@ -358,7 +352,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(L2B_STC007_worker, SIGNAL(newBlockProcessed(STC007DataBlock)), this, SLOT(receivePCMDataBlock(STC007DataBlock))); connect(L2B_STC007_worker, SIGNAL(newBlockProcessed(STC007DataBlock)), this, SLOT(updateStatsBlockTime(STC007DataBlock))); connect(L2B_STC007_worker, SIGNAL(guiUpdFrameAsm(FrameAsmSTC007)), this, SLOT(updateStatsFrameAsm(FrameAsmSTC007))); - connect(L2B_STC007_worker, SIGNAL(loopTime(quint64)), this, SLOT(updateDebugBar(quint64))); + //connect(L2B_STC007_worker, SIGNAL(loopTime(quint64)), this, SLOT(updateDebugBar(quint64))); // Create and link audio processor worker. audio_PU = NULL; @@ -378,9 +372,10 @@ MainWindow::MainWindow(QWidget *parent) : connect(this, SIGNAL(newMaskingMode(uint8_t)), AP_worker, SLOT(setMasking(uint8_t))); connect(this, SIGNAL(newEnableLivePB(bool)), AP_worker, SLOT(setOutputToLive(bool))); connect(this, SIGNAL(newEnableWaveSave(bool)), AP_worker, SLOT(setOutputToFile(bool))); + connect(AP_worker, SIGNAL(mediaError(QString)), this, SLOT(displayErrorMessage(QString))); connect(AP_worker, SIGNAL(guiAddMask(uint16_t)), this, SLOT(updateStatsMaskes(uint16_t))); connect(AP_worker, SIGNAL(guiLivePB(bool)), this, SLOT(livePBUpdate(bool))); - connect(AP_worker, SIGNAL(outSamples(PCMSamplePair)), this, SLOT(updateVU(PCMSamplePair))); + connect(AP_worker, SIGNAL(outVULevels(uint8_t,uint8_t)), this, SLOT(receiveVUMeters(uint8_t,uint8_t))); connect(this, SIGNAL(newFineReset()), this, SLOT(setDefaultFineSettings())); connect(this, SIGNAL(newFineReset()), VIN_worker, SLOT(setDefaultFineSettings())); @@ -391,16 +386,15 @@ MainWindow::MainWindow(QWidget *parent) : // Start new thread with binarizer. conv_V2D->start(QThread::InheritPriority); // Start new thread with deinterleaver/frame assembler. - //conv_L2B->start(QThread::LowPriority); conv_L2B_PCM1->start(QThread::InheritPriority); conv_L2B_PCM16X0->start(QThread::InheritPriority); conv_L2B_STC007->start(QThread::InheritPriority); // Start new thread with audio processor. - //audio_PU->start(QThread::LowestPriority); + //audio_PU->start(QThread::HighPriority); audio_PU->start(QThread::InheritPriority); qInfo()<<"[M] Application path:"<applicationDirPath(); - // Code can hang here is antivirus software locks access to storage or storage has problems. + // Code can hang here if antivirus software locks access to storage or storage has problems. qInfo()<<"[M] Waiting for translations to load..."; // Regenerate language submenu. updateGUILangList(); @@ -410,8 +404,6 @@ MainWindow::MainWindow(QWidget *parent) : // Start UI counters updater. timUIUpdate.start(); - // Start thread running checker. - timTRDUpdate.start(); //buffer_tester(); } @@ -446,7 +438,6 @@ void MainWindow::closeEvent(QCloseEvent *event) qInfo()<<"[M] Shutting down..."; // Stop GUI update and thread check. timUIUpdate.stop(); - timTRDUpdate.stop(); // Notify all threads about exiting. emit aboutToExit(); @@ -643,17 +634,19 @@ void MainWindow::setGUILanguage(QString in_locale, bool suppress) readGUISettings(); } -//------------------------ Set options for [vin_processor] module. +//------------------------ Set options for [VideoInFFMPEG] module. void MainWindow::setVIPOptions() { + // Stepped playback. emit newStepPlay(ui->cbxFrameStep->isChecked()); + // Set frame drop detection. emit newFrameDropDetection(ui->cbxFrameDropout->isChecked()); } -//------------------------ Set options for [videotodigital] and [Binarizer] modules. +//------------------------ Set options for [VideoToDigital] and [Binarizer] modules. void MainWindow::setLBOptions() { - // Set PCM type for V2D. + // Set PCM type. if(set_pcm_type!=ui->lbxPCMType->currentIndex()) { if(ui->lbxPCMType->currentIndex()==LIST_TYPE_PCM1) @@ -670,11 +663,11 @@ void MainWindow::setLBOptions() } else { - qWarning()<lbxPCMType->currentIndex(); } - // Set binarization mode for V2D. + // Set binarization mode. if(ui->lbxBinQuality->currentIndex()==LIST_BQ_FAST) { emit newBinMode(Binarizer::MODE_FAST); @@ -693,17 +686,17 @@ void MainWindow::setLBOptions() } else { - qWarning()<cbxLineDuplicate->isChecked()); } -//------------------------ Set options for [stc007datastitcher] and [stc007deinterleaver] modules. +//------------------------ Set options for [xDataStitcher] and [xDeinterleaver] modules. void MainWindow::setDIOptions() { // PCM-1 settings. - // Preset PCM-1 field order for L2B. + // Preset PCM-1 field order. if(ui->lbxPCM1FieldOrder->currentIndex()==LIST_PCM1_FO_BFF) { emit newPCM1FieldOrder(FrameAsmDescriptor::ORDER_BFF); @@ -713,12 +706,42 @@ void MainWindow::setDIOptions() emit newPCM1FieldOrder(FrameAsmDescriptor::ORDER_TFF); if(ui->lbxPCM1FieldOrder->currentIndex()!=LIST_PCM1_FO_TFF) { - qWarning()<lbxPCM1FieldOrder->currentIndex(); + qWarning()<lbxPCM1FieldOrder->currentIndex(); + } + } + // Preset line offset. + if(ui->cbxPCM1Offset->isChecked()!=false) + { + ui->sldPCM1OddOfs->setEnabled(false); + ui->sldPCM1EvenOfs->setEnabled(false); + ui->lblPCM1OddOfs->setEnabled(false); + ui->lblPCM1EvenOfs->setEnabled(false); + ui->edtPCM1OddOfs->setEnabled(false); + ui->edtPCM1EvenOfs->setEnabled(false); + } + else + { + ui->sldPCM1OddOfs->setEnabled(true); + if(ui->btnPCM1OfsSync->isChecked()!=false) + { + ui->sldPCM1EvenOfs->setEnabled(false); + ui->sldPCM1EvenOfs->setValue(ui->sldPCM1OddOfs->value()-1); + } + else + { + ui->sldPCM1EvenOfs->setEnabled(true); } + ui->lblPCM1OddOfs->setEnabled(true); + ui->lblPCM1EvenOfs->setEnabled(true); + ui->edtPCM1OddOfs->setEnabled(true); + ui->edtPCM1EvenOfs->setEnabled(true); } + emit newPCM1AutoOffset(ui->cbxPCM1Offset->isChecked()); + emit newPCM1OddOffset((int8_t)ui->sldPCM1OddOfs->value()); + emit newPCM1EvenOffset((int8_t)ui->sldPCM1EvenOfs->value()); // PCM-16x0 settings. - // Preset PCM-16x0 mode/format for L2B. + // Preset PCM-16x0 mode/format. if(ui->lbxPCM16x0Format->currentIndex()==LIST_PCM16X0_FMT_EI) { emit newPCM16x0Format(PCM16X0Deinterleaver::FORMAT_EI); @@ -735,10 +758,10 @@ void MainWindow::setDIOptions() /*emit new16x0Format(PCM16X0Deinterleaver::FORMAT_AUTO); if(ui->lbxPCM16x0Format->currentIndex()!=LIST_16X0_AUTO) { - qWarning()<lbxPCM16x0Format->currentIndex(); + qWarning()<lbxPCM16x0Format->currentIndex(); }*/ } - // Preset PCM-16x0 field order for L2B. + // Preset PCM-16x0 field order. if(ui->lbxPCM16x0FieldOrder->currentIndex()==LIST_PCM16X0_FO_BFF) { emit newPCM16x0FieldOrder(FrameAsmDescriptor::ORDER_BFF); @@ -748,10 +771,10 @@ void MainWindow::setDIOptions() emit newPCM16x0FieldOrder(FrameAsmDescriptor::ORDER_TFF); if(ui->lbxPCM16x0FieldOrder->currentIndex()!=LIST_PCM16X0_FO_TFF) { - qWarning()<lbxPCM16x0FieldOrder->currentIndex(); + qWarning()<lbxPCM16x0FieldOrder->currentIndex(); } } - // Preset PCM-16x0 P correction settings for L2B. + // Preset PCM-16x0 error correction settings. if(ui->lbxPCM16x0ECC->currentIndex()==LIST_PCM16X0_ECC_NONE) { emit newPCM16x0PCorrection(false); @@ -761,10 +784,10 @@ void MainWindow::setDIOptions() emit newPCM16x0PCorrection(true); if(ui->lbxPCM16x0ECC->currentIndex()!=LIST_PCM16X0_ECC_PARITY) { - qWarning()<lbxPCM16x0ECC->currentIndex(); + qWarning()<lbxPCM16x0ECC->currentIndex(); } } - // Preset PCM-16x0 audio sample rate for L2B. + // Preset PCM-16x0 audio sample rate. if(ui->lbxPCM16x0SampleRate->currentIndex()==LIST_PCM16X0_SRATE_44100) { emit newPCM16x0SampleRatePreset(PCMSamplePair::SAMPLE_RATE_44100); @@ -778,12 +801,12 @@ void MainWindow::setDIOptions() emit newPCM16x0SampleRatePreset(PCMSamplePair::SAMPLE_RATE_AUTO); if(ui->lbxPCM16x0SampleRate->currentIndex()!=LIST_PCM16X0_SRATE_AUTO) { - qWarning()<lbxPCM16x0SampleRate->currentIndex(); + qWarning()<lbxPCM16x0SampleRate->currentIndex(); } } // STC-007 settings. - // Preset STC-007 video standard for L2B. + // Preset STC-007 video standard. if(ui->lbxSTC007VidStandard->currentIndex()==LIST_STC007_VID_NTSC) { emit newSTC007VidStandard(FrameAsmDescriptor::VID_NTSC); @@ -797,10 +820,10 @@ void MainWindow::setDIOptions() emit newSTC007VidStandard(FrameAsmDescriptor::VID_UNKNOWN); if(ui->lbxSTC007VidStandard->currentIndex()!=LIST_STC007_VID_AUTO) { - qWarning()<lbxSTC007VidStandard->currentIndex(); + qWarning()<lbxSTC007VidStandard->currentIndex(); } } - // Preset STC-007 field order for L2B. + // Preset STC-007 field order. if(ui->lbxSTC007FieldOrder->currentIndex()==LIST_STC007_FO_TFF) { emit newSTC007FieldOrder(FrameAsmDescriptor::ORDER_TFF); @@ -814,10 +837,10 @@ void MainWindow::setDIOptions() emit newSTC007FieldOrder(FrameAsmDescriptor::ORDER_UNK); if(ui->lbxSTC007FieldOrder->currentIndex()!=LIST_STC007_FO_AUTO) { - qWarning()<lbxSTC007FieldOrder->currentIndex(); + qWarning()<lbxSTC007FieldOrder->currentIndex(); } } - // Set STC-007 P and Q correction settings for L2B. + // Set STC-007 error correction settings. if(ui->lbxSTC007ECC->currentIndex()==LIST_STC007_ECC_NONE) { emit newSTC007PCorrection(false); @@ -834,10 +857,10 @@ void MainWindow::setDIOptions() emit newSTC007QCorrection(true); if(ui->lbxSTC007ECC->currentIndex()!=LIST_STC007_ECC_FULL) { - qWarning()<lbxSTC007ECC->currentIndex(); + qWarning()<lbxSTC007ECC->currentIndex(); } } - // Set STC-007 CWD correction settings for L2B. + // Set STC-007 CWD correction settings. if(ui->lbxSTC007CWD->currentIndex()==LIST_STC007_CWD_DIS) { emit newSTC007CWDCorrection(false); @@ -847,10 +870,10 @@ void MainWindow::setDIOptions() emit newSTC007CWDCorrection(true); if(ui->lbxSTC007CWD->currentIndex()!=LIST_STC007_CWD_EN) { - qWarning()<lbxSTC007CWD->currentIndex(); + qWarning()<lbxSTC007CWD->currentIndex(); } } - // Preset STC-007 audio resolution for L2B. + // Preset STC-007 audio resolution. if(ui->lbxSTC007Resolution->currentIndex()==LIST_STC007_RES_14BIT) { emit newSTC007ResolutionPreset(STC007DataStitcher::SAMPLE_RES_14BIT); @@ -864,10 +887,10 @@ void MainWindow::setDIOptions() emit newSTC007ResolutionPreset(STC007DataStitcher::SAMPLE_RES_UNKNOWN); if(ui->lbxSTC007Resolution->currentIndex()!=LIST_STC007_RES_AUTO) { - qWarning()<lbxSTC007Resolution->currentIndex(); + qWarning()<lbxSTC007Resolution->currentIndex(); } } - // Preset STC-007 audio sample rate for L2B. + // Preset STC-007 audio sample rate. if(ui->lbxSTC007SampleRate->currentIndex()==LIST_STC007_SRATE_44056) { emit newSTC007SampleRatePreset(PCMSamplePair::SAMPLE_RATE_44056); @@ -881,12 +904,12 @@ void MainWindow::setDIOptions() emit newSTC007SampleRatePreset(PCMSamplePair::SAMPLE_RATE_AUTO); if(ui->lbxSTC007SampleRate->currentIndex()!=LIST_STC007_SRATE_AUTO) { - qWarning()<lbxSTC007SampleRate->currentIndex(); + qWarning()<lbxSTC007SampleRate->currentIndex(); } } } -//------------------------ Set options for [audioprocessor] and [stc007towav] modules. +//------------------------ Set options for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. void MainWindow::setAPOptions() { int index; @@ -922,11 +945,11 @@ void MainWindow::setAPOptions() } else { - qWarning()<lbxDropAction->currentIndex(); + qWarning()<lbxDropAction->currentIndex(); } - // Set live playback settings for AP. + // Set live playback settings. emit newEnableLivePB(ui->cbxLivePB->isChecked()); - // Set save to file settings for AP. + // Set save to file settings. emit newEnableWaveSave(ui->cbxWaveSave->isChecked()); } @@ -938,7 +961,7 @@ void MainWindow::setMainLogMode() if(ui->actGenProcess->isChecked()!=false) log_level |= LOG_PROCESS; } -//------------------------ Set debug logging mode for [vin_processor] module. +//------------------------ Set debug logging mode for [VideoInFFMPEG] module. void MainWindow::setVIPLogMode() { uint8_t ext_log_vip = 0; @@ -949,7 +972,7 @@ void MainWindow::setVIPLogMode() emit newVIPLogLevel(ext_log_vip); } -//------------------------ Set debug logging mode for [videotodigital] and [Binarizer] modules. +//------------------------ Set debug logging mode for [VideoToDigital] and [Binarizer] modules. void MainWindow::setLBLogMode() { uint8_t ext_log_lb = 0; @@ -963,7 +986,7 @@ void MainWindow::setLBLogMode() emit newV2DLogLevel(ext_log_lb); } -//------------------------ Set debug logging mode for [stc007datastitcher] and [stc007deinterleaver] modules. +//------------------------ Set debug logging mode for [xDataStitcher] and [xDeinterleaver] modules. void MainWindow::setDILogMode() { uint16_t ext_log_di = 0; @@ -980,7 +1003,7 @@ void MainWindow::setDILogMode() emit newL2BLogLevel(ext_log_di); } -//------------------------ Set debug logging mode for [audioprocessor] and [stc007towav] modules. +//------------------------ Set debug logging mode for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. void MainWindow::setAPLogMode() { uint8_t ext_log_ap = 0; @@ -994,21 +1017,22 @@ void MainWindow::setAPLogMode() } -//------------------------ Disable comboboxes events to prevent switching settings to default while changing GUI translation. +//------------------------ Disable GUI events to prevent switching settings to default while changing GUI translation. void MainWindow::disableGUIEvents() { inhibit_setting_save = true; } -//------------------------ Re-enable comboboxes events after changing translation. +//------------------------ Re-enable GUI events after changing translation. void MainWindow::enableGUIEvents() { inhibit_setting_save = false; } -//------------------------ Apply GUI settings to the decoder. +//------------------------ Apply GUI settings to different modules. void MainWindow::applyGUISettings() { + // First, switch some things in GUI. // Toggle live playback indicator. if(ui->cbxLivePB->isChecked()==false) { @@ -1018,7 +1042,6 @@ void MainWindow::applyGUISettings() { ui->lblLivePB->setEnabled(true); } - // Toggle frame drop indicator. if(ui->cbxFrameDropout->isChecked()==false) { @@ -1030,7 +1053,6 @@ void MainWindow::applyGUISettings() ui->lblFrameDrop->setEnabled(true); ui->lcdFrameDrop->setEnabled(true); } - // Toggle duplicated line indicator. if(ui->cbxLineDuplicate->isChecked()==false) { @@ -1042,14 +1064,12 @@ void MainWindow::applyGUISettings() ui->lblDupErr->setEnabled(true); ui->lcdDupErr->setEnabled(true); } - // Choose what to display according to selected PCM type. if(ui->lbxPCMType->currentIndex()==LIST_TYPE_PCM1) { // Select pages for the format. ui->stcDecoderSettings->setCurrentIndex(LIST_TYPE_PCM1); ui->stcFrameAsm->setCurrentIndex(LIST_TYPE_PCM1); - // Enable controls on showed pages, disable on others. ui->pgPCM1Settings->setEnabled(true); ui->pgPCM1Frame->setEnabled(true); @@ -1057,7 +1077,6 @@ void MainWindow::applyGUISettings() ui->pgPCM16x0Frame->setEnabled(false); ui->pgSTC007Settings->setEnabled(false); ui->pgSTC007Frame->setEnabled(false); - // Show/hide stats indicators. ui->lblBadStitch->setEnabled(false); ui->lcdBadStitch->setEnabled(false); @@ -1065,6 +1084,8 @@ void MainWindow::applyGUISettings() ui->lcdPCorr->setEnabled(false); ui->lblQCorr->setEnabled(false); ui->lcdQCorr->setEnabled(false); + ui->lblCWDCorr->setEnabled(false); + ui->lcdCWDCorr->setEnabled(false); ui->lblBroken->setEnabled(false); ui->lcdBroken->setEnabled(false); } @@ -1073,7 +1094,6 @@ void MainWindow::applyGUISettings() // Select pages for the format. ui->stcDecoderSettings->setCurrentIndex(LIST_TYPE_PCM16X0); ui->stcFrameAsm->setCurrentIndex(LIST_TYPE_PCM16X0); - // Enable controls on showed pages, disable on others. ui->pgPCM1Settings->setEnabled(false); ui->pgPCM1Frame->setEnabled(false); @@ -1081,16 +1101,17 @@ void MainWindow::applyGUISettings() ui->pgPCM16x0Frame->setEnabled(true); ui->pgSTC007Settings->setEnabled(false); ui->pgSTC007Frame->setEnabled(false); - // Show/hide stats indicators. ui->lblBadStitch->setEnabled(false); ui->lcdBadStitch->setEnabled(false); - if(ui->lbxSTC007ECC->currentIndex()==LIST_STC007_ECC_NONE) + if(ui->lbxPCM16x0ECC->currentIndex()==LIST_PCM16X0_ECC_NONE) { ui->lblPCorr->setEnabled(false); ui->lcdPCorr->setEnabled(false); ui->lblQCorr->setEnabled(false); ui->lcdQCorr->setEnabled(false); + ui->lblCWDCorr->setEnabled(false); + ui->lcdCWDCorr->setEnabled(false); } else { @@ -1098,6 +1119,8 @@ void MainWindow::applyGUISettings() ui->lcdPCorr->setEnabled(true); ui->lblQCorr->setEnabled(false); ui->lcdQCorr->setEnabled(false); + ui->lblCWDCorr->setEnabled(false); + ui->lcdCWDCorr->setEnabled(false); } ui->lblBroken->setEnabled(true); ui->lcdBroken->setEnabled(true); @@ -1107,7 +1130,6 @@ void MainWindow::applyGUISettings() // Select pages for the format. ui->stcDecoderSettings->setCurrentIndex(LIST_TYPE_STC007); ui->stcFrameAsm->setCurrentIndex(LIST_TYPE_STC007); - // Enable controls on showed pages, disable on others. ui->pgPCM1Settings->setEnabled(false); ui->pgPCM1Frame->setEnabled(false); @@ -1115,7 +1137,6 @@ void MainWindow::applyGUISettings() ui->pgPCM16x0Frame->setEnabled(false); ui->pgSTC007Settings->setEnabled(true); ui->pgSTC007Frame->setEnabled(true); - // Show/hide stats indicators. ui->lblBadStitch->setEnabled(true); ui->lcdBadStitch->setEnabled(true); @@ -1140,33 +1161,41 @@ void MainWindow::applyGUISettings() ui->lblQCorr->setEnabled(false); ui->lcdQCorr->setEnabled(false); } + if(ui->lbxSTC007CWD->currentIndex()==LIST_STC007_CWD_DIS) + { + ui->lblCWDCorr->setEnabled(false); + ui->lcdCWDCorr->setEnabled(false); + } + else if(ui->lbxSTC007ECC->currentIndex()!=LIST_STC007_ECC_NONE) + { + ui->lblCWDCorr->setEnabled(true); + ui->lcdCWDCorr->setEnabled(true); + } + else + { + ui->lblCWDCorr->setEnabled(false); + ui->lcdCWDCorr->setEnabled(false); + } ui->lblBroken->setEnabled(true); ui->lcdBroken->setEnabled(true); } - - ui->lbxDropAction->setEnabled(true); + // Choose what counter display for sample errors. if((ui->lbxDropAction->currentIndex()==LIST_DOA_MUTE_WORD)||(ui->lbxDropAction->currentIndex()==LIST_DOA_MUTE_BLOCK)) { ui->lblMask->setEnabled(false); ui->lcdMask->setEnabled(false); - ui->lblMute->setEnabled(true); - ui->lcdMute->setEnabled(true); } else if(ui->lbxDropAction->currentIndex()==LIST_DOA_SKIP) { ui->lblMask->setEnabled(false); ui->lcdMask->setEnabled(false); - ui->lblMute->setEnabled(false); - ui->lcdMute->setEnabled(false); } else { ui->lblMask->setEnabled(true); ui->lcdMask->setEnabled(true); - ui->lblMute->setEnabled(true); - ui->lcdMute->setEnabled(true); } - + // Finally, perform per-module settings applying. setVIPOptions(); setLBOptions(); setDIOptions(); @@ -1208,6 +1237,9 @@ void MainWindow::readGUISettings() ui->lbxBinQuality->setCurrentIndex(settings_hdl.value("bin_quality", LIST_BQ_FAST).toInt()); ui->lbxPCMType->setCurrentIndex(settings_hdl.value("pcm_type", LIST_TYPE_STC007).toInt()); ui->lbxPCM1FieldOrder->setCurrentIndex(settings_hdl.value("pcm1_field_order", LIST_PCM1_FO_TFF).toInt()); + ui->cbxPCM1Offset->setChecked(settings_hdl.value("pcm1_auto_offset", true).toBool()); + ui->sldPCM1OddOfs->setValue(settings_hdl.value("pcm1_odd_offset", 0).toInt()); + ui->sldPCM1EvenOfs->setValue(settings_hdl.value("pcm1_even_offset", -1).toInt()); ui->lbxPCM16x0Format->setCurrentIndex(settings_hdl.value("pcm16x0_fmt", LIST_PCM16X0_FMT_SI).toInt()); ui->lbxPCM16x0FieldOrder->setCurrentIndex(settings_hdl.value("pcm16x0_field_order", LIST_PCM16X0_FO_TFF).toInt()); ui->lbxPCM16x0ECC->setCurrentIndex(settings_hdl.value("pcm16x0_ecc", LIST_PCM16X0_ECC_PARITY).toInt()); @@ -1280,7 +1312,7 @@ void MainWindow::readGUISettings() setDILogMode(); setAPLogMode(); - // Apply settings. + // Apply settings to all modules. applyGUISettings(); enableGUIEvents(); @@ -1301,7 +1333,25 @@ CoordinatePair MainWindow::getCoordByFrameNo(uint32_t frame_num) return coord_res; } -//------------------------ Save new window position and size in setting storage. +//------------------------ Exit application. +void MainWindow::exitAction() +{ + if((log_level&LOG_PROCESS)!=0) + { + qInfo()<<"[M] Exiting..."; + } + emit doPlayStop(); + emit doPlayUnload(); + this->close(); +} + +//------------------------ User request to set GUI language. +void MainWindow::setLang(QAction *in_act) +{ + setGUILanguage(in_act->data().toString()); +} + +//------------------------ Save new main window position and size in setting storage. void MainWindow::updateWindowPosition() { qInfo()<<"[M] Position saved"<geometry()<pos(); @@ -1312,43 +1362,16 @@ void MainWindow::updateWindowPosition() settings_hdl.endGroup(); } -//------------------------ Display window with an error. +//------------------------ Display window with an error, stop playback. void MainWindow::displayErrorMessage(QString in_string) { + // Stop playback if any. + emit doPlayStop(); + // Display error message. QMessageBox::critical(this, tr("Ошибка"), in_string); } -//------------------------ Set GUI language. -void MainWindow::setLang(QAction *in_act) -{ - setGUILanguage(in_act->data().toString()); -} - -//------------------------ Start video playback/decode. -void MainWindow::playVideo() -{ - ui->btnPlay->setEnabled(false); - ui->btnPause->setEnabled(false); - ui->cbxWaveSave->setEnabled(false); - if(v_decoder_state==VDEC_STOP) - { - qDebug()<<"[M] Play request"; - emit doPlayStart(); - } - else - { - qDebug()<<"[M] Stop request"; - emit doPlayStop(); - } -} - -//------------------------ Pause video playback/decode. -void MainWindow::pauseVideo() -{ - ui->btnPause->setEnabled(false); - emit doPlayPause(); -} - +//------------------------ User request to open a new source. void MainWindow::loadVideo() { if((log_level&LOG_PROCESS)!=0) @@ -1395,34 +1418,43 @@ void MainWindow::loadVideo() } } +//------------------------ User request to close the source and free resources. void MainWindow::unloadSource() { emit doPlayUnload(); } -void MainWindow::loadPicture() +//------------------------ User request to start/stop video playback/decode. +void MainWindow::usrPlayStop() { - if((log_level&LOG_PROCESS)!=0) + ui->btnPlay->setEnabled(false); + ui->btnPause->setEnabled(false); + ui->cbxWaveSave->setEnabled(false); + if(v_decoder_state==VDEC_STOP) + { + qDebug()<<"[M] Play request"; + emit doPlayStart(); + } + else { - qInfo()<<"[M] Creating 'Open picture' dialog..."; + qDebug()<<"[M] Stop request"; + emit doPlayStop(); } } -void MainWindow::exitAction() +//------------------------ User request to pause video playback/decode. +void MainWindow::usrPause() { - if((log_level&LOG_PROCESS)!=0) - { - qInfo()<<"[M] Exiting..."; - } - emit doPlayStop(); - emit doPlayUnload(); - this->close(); + ui->btnPause->setEnabled(false); + emit doPlayPause(); } //------------------------ Save settings for GUI options. void MainWindow::updateGUISettings() { + // Check if settings updating is disabled due to GUI switching. if(inhibit_setting_save!=false) return; + // Open settings storage. QSettings settings_hdl(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); settings_hdl.beginGroup("decoder"); // Check if PCM type was changed (not saved in settings yet) @@ -1437,7 +1469,7 @@ void MainWindow::updateGUISettings() frame_asm_stc007.clear(); } settings_hdl.endGroup(); - + // Save GUI settings. settings_hdl.beginGroup("player"); settings_hdl.setValue("live_pb", ui->cbxLivePB->isChecked()); settings_hdl.setValue("wave_save", ui->cbxWaveSave->isChecked()); @@ -1445,11 +1477,13 @@ void MainWindow::updateGUISettings() settings_hdl.setValue("drop_detect", ui->cbxFrameDropout->isChecked()); settings_hdl.setValue("framestep", ui->cbxFrameStep->isChecked()); settings_hdl.endGroup(); - settings_hdl.beginGroup("decoder"); settings_hdl.setValue("bin_quality", ui->lbxBinQuality->currentIndex()); settings_hdl.setValue("pcm_type", ui->lbxPCMType->currentIndex()); settings_hdl.setValue("pcm1_field_order", ui->lbxPCM1FieldOrder->currentIndex()); + settings_hdl.setValue("pcm1_auto_offset", ui->cbxPCM1Offset->isChecked()); + settings_hdl.setValue("pcm1_odd_offset", ui->sldPCM1OddOfs->value()); + settings_hdl.setValue("pcm1_even_offset", ui->sldPCM1EvenOfs->value()); settings_hdl.setValue("pcm16x0_fmt", ui->lbxPCM16x0Format->currentIndex()); settings_hdl.setValue("pcm16x0_field_order", ui->lbxPCM16x0FieldOrder->currentIndex()); settings_hdl.setValue("pcm16x0_ecc", ui->lbxPCM16x0ECC->currentIndex()); @@ -1463,8 +1497,7 @@ void MainWindow::updateGUISettings() settings_hdl.setValue("drop_action", ui->lbxDropAction->currentIndex()); settings_hdl.endGroup(); - settings_hdl.sync(); - + // Apply all settings from the GUI to all modules. applyGUISettings(); } @@ -1498,7 +1531,6 @@ void MainWindow::clearStat() stat_broken_block_cnt = 0; stat_drop_block_cnt = 0; stat_drop_sample_cnt = 0; - stat_mute_cnt = 0; stat_mask_cnt = 0; stat_processed_frame_cnt = 0; stat_line_cnt = 0; @@ -1511,12 +1543,19 @@ void MainWindow::clearStat() ui->lcdBadStitch->display(0); ui->lcdPCorr->display(0); ui->lcdQCorr->display(0); + ui->lcdCWDCorr->display(0); ui->lcdDropout->display(0); - ui->lcdMute->display(0); ui->lcdMask->display(0); ui->lcdProcessedFrames->display(0); } +//------------------------ +void MainWindow::sliderDisplayUpdate() +{ + ui->edtPCM1OddOfs->setText(QString::number(ui->sldPCM1OddOfs->sliderPosition())); + ui->edtPCM1EvenOfs->setText(QString::number(ui->sldPCM1EvenOfs->sliderPosition())); +} + //------------------------ Confirm and reset decoder settings. void MainWindow::resetOptDecoder() { @@ -1534,12 +1573,12 @@ void MainWindow::resetOptDecoder() settings_hdl.beginGroup("decoder"); settings_hdl.remove(""); settings_hdl.endGroup(); - // Reload settings into GUI. + // Reload default settings into GUI. readGUISettings(); } } -//------------------------ Confirm and reset visualizer windows. +//------------------------ Confirm and reset visualizer windows positions. void MainWindow::resetVisPositions() { QMessageBox usrConfirm(this); @@ -1585,7 +1624,7 @@ void MainWindow::resetFull() QSettings settings_hdl(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); // Remove ALL settings. settings_hdl.clear(); - // Reload settings into GUI. + // Reload default settings into GUI. readGUISettings(); // Reset all fine settings. emit newFineReset(); @@ -1595,94 +1634,95 @@ void MainWindow::resetFull() //------------------------ Display "About" window. void MainWindow::showAbout() { - about_wnd about_dlg; + about_wnd about_dlg(this); about_dlg.exec(); } //------------------------ Display video capture selection dialog. void MainWindow::showCaptureSelector() { - captureSelectDialog = new capt_sel(this); - - captureSelectDialog->exec(); - captureSelectDialog->deleteLater(); + //captureSelectDialog = new capt_sel(this); + capt_sel captureSelectDialog(this); + captureSelectDialog.exec(); + //captureSelectDialog->deleteLater(); } //------------------------ Display video processor fine settings dialog. void MainWindow::showVidInFineSettings() { - vipFineSetDialog = new (std::nothrow) fine_vidin_set(this); + //vipFineSetDialog = new (std::nothrow) fine_vidin_set(this); + fine_vidin_set vipFineSetDialog(this); //connect(VIN_worker, SIGNAL(guiUpdFineLineSkip(bool)), vipFineSetDialog, SLOT(newSkipLines(bool))); - connect(VIN_worker, SIGNAL(guiUpdFineSettings(vid_preset_t)), vipFineSetDialog, SLOT(newSettings(vid_preset_t))); - connect(this, SIGNAL(guiUpdFineDrawDeint(bool)), vipFineSetDialog, SLOT(newDrawDeint(bool))); - connect(vipFineSetDialog, SIGNAL(setFineDefaults()), VIN_worker, SLOT(setDefaultFineSettings())); - connect(vipFineSetDialog, SIGNAL(requestFineCurrent()), VIN_worker, SLOT(requestCurrentFineSettings())); - connect(vipFineSetDialog, SIGNAL(setFineCurrent(vid_preset_t)), VIN_worker, SLOT(setFineSettings(vid_preset_t))); - connect(vipFineSetDialog, SIGNAL(setFineDefaults()), this, SLOT(setDefaultFineSettings())); - connect(vipFineSetDialog, SIGNAL(requestFineCurrent()), this, SLOT(requestCurrentFineSettings())); - connect(vipFineSetDialog, SIGNAL(setDrawDeint(bool)), this, SLOT(setFineDrawDeint(bool))); - vipFineSetDialog->exec(); - vipFineSetDialog->deleteLater(); + connect(VIN_worker, SIGNAL(guiUpdFineSettings(vid_preset_t)), &vipFineSetDialog, SLOT(newSettings(vid_preset_t))); + connect(this, SIGNAL(guiUpdFineDrawDeint(bool)), &vipFineSetDialog, SLOT(newDrawDeint(bool))); + connect(&vipFineSetDialog, SIGNAL(setFineDefaults()), VIN_worker, SLOT(setDefaultFineSettings())); + connect(&vipFineSetDialog, SIGNAL(requestFineCurrent()), VIN_worker, SLOT(requestCurrentFineSettings())); + connect(&vipFineSetDialog, SIGNAL(setFineCurrent(vid_preset_t)), VIN_worker, SLOT(setFineSettings(vid_preset_t))); + connect(&vipFineSetDialog, SIGNAL(setFineDefaults()), this, SLOT(setDefaultFineSettings())); + connect(&vipFineSetDialog, SIGNAL(requestFineCurrent()), this, SLOT(requestCurrentFineSettings())); + connect(&vipFineSetDialog, SIGNAL(setDrawDeint(bool)), this, SLOT(setFineDrawDeint(bool))); + vipFineSetDialog.exec(); + //vipFineSetDialog->deleteLater(); } //------------------------ Display binarizator fine settings dialog. void MainWindow::showBinFineSettings() { - binFineSetDialog = new fine_bin_set(this); - connect(V2D_worker, SIGNAL(guiUpdFineSettings(bin_preset_t)), binFineSetDialog, SLOT(newSettings(bin_preset_t))); - connect(binFineSetDialog, SIGNAL(setFineDefaults()), V2D_worker, SLOT(setDefaultFineSettings())); - connect(binFineSetDialog, SIGNAL(requestFineCurrent()), V2D_worker, SLOT(requestCurrentFineSettings())); - connect(binFineSetDialog, SIGNAL(setFineCurrent(bin_preset_t)), V2D_worker, SLOT(setFineSettings(bin_preset_t))); - binFineSetDialog->exec(); - binFineSetDialog->deleteLater(); + //binFineSetDialog = new fine_bin_set(this); + fine_bin_set binFineSetDialog(this); + connect(V2D_worker, SIGNAL(guiUpdFineSettings(bin_preset_t)), &binFineSetDialog, SLOT(newSettings(bin_preset_t))); + connect(&binFineSetDialog, SIGNAL(setFineDefaults()), V2D_worker, SLOT(setDefaultFineSettings())); + connect(&binFineSetDialog, SIGNAL(requestFineCurrent()), V2D_worker, SLOT(requestCurrentFineSettings())); + connect(&binFineSetDialog, SIGNAL(setFineCurrent(bin_preset_t)), V2D_worker, SLOT(setFineSettings(bin_preset_t))); + binFineSetDialog.exec(); + //binFineSetDialog->deleteLater(); } //------------------------ Display deinterleaver fine settings dialog. void MainWindow::showDeintFineSettings() { - deintFineSetDialog = new fine_deint_set(this); - + //deintFineSetDialog = new fine_deint_set(this); + fine_deint_set deintFineSetDialog(this); if(set_pcm_type==LIST_TYPE_PCM1) { - connect(L2B_PCM1_worker, SIGNAL(guiUpdFineUseECC(bool)), deintFineSetDialog, SLOT(newUseECC(bool))); + connect(L2B_PCM1_worker, SIGNAL(guiUpdFineUseECC(bool)), &deintFineSetDialog, SLOT(newUseECC(bool))); - connect(deintFineSetDialog, SIGNAL(setFineDefaults()), L2B_PCM1_worker, SLOT(setDefaultFineSettings())); - connect(deintFineSetDialog, SIGNAL(requestFineCurrent()), L2B_PCM1_worker, SLOT(requestCurrentFineSettings())); - connect(deintFineSetDialog, SIGNAL(setUseECC(bool)), L2B_PCM1_worker, SLOT(setFineUseECC(bool))); + connect(&deintFineSetDialog, SIGNAL(setFineDefaults()), L2B_PCM1_worker, SLOT(setDefaultFineSettings())); + connect(&deintFineSetDialog, SIGNAL(requestFineCurrent()), L2B_PCM1_worker, SLOT(requestCurrentFineSettings())); + connect(&deintFineSetDialog, SIGNAL(setUseECC(bool)), L2B_PCM1_worker, SLOT(setFineUseECC(bool))); } else if(set_pcm_type==LIST_TYPE_PCM16X0) { - connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFineUseECC(bool)), deintFineSetDialog, SLOT(newUseECC(bool))); - connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFineMaskSeams(bool)), deintFineSetDialog, SLOT(newMaskSeams(bool))); - connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFineBrokeMask(uint8_t)), deintFineSetDialog, SLOT(newBrokeMask(uint8_t))); + connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFineUseECC(bool)), &deintFineSetDialog, SLOT(newUseECC(bool))); + connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFineMaskSeams(bool)), &deintFineSetDialog, SLOT(newMaskSeams(bool))); + connect(L2B_PCM16X0_worker, SIGNAL(guiUpdFineBrokeMask(uint8_t)), &deintFineSetDialog, SLOT(newBrokeMask(uint8_t))); - connect(deintFineSetDialog, SIGNAL(setFineDefaults()), L2B_PCM16X0_worker, SLOT(setDefaultFineSettings())); - connect(deintFineSetDialog, SIGNAL(requestFineCurrent()), L2B_PCM16X0_worker, SLOT(requestCurrentFineSettings())); - connect(deintFineSetDialog, SIGNAL(setUseECC(bool)), L2B_PCM16X0_worker, SLOT(setFineUseECC(bool))); - connect(deintFineSetDialog, SIGNAL(setMaskSeams(bool)), L2B_PCM16X0_worker, SLOT(setFineMaskSeams(bool))); - connect(deintFineSetDialog, SIGNAL(setBrokeMask(uint8_t)), L2B_PCM16X0_worker, SLOT(setFineBrokeMask(uint8_t))); + connect(&deintFineSetDialog, SIGNAL(setFineDefaults()), L2B_PCM16X0_worker, SLOT(setDefaultFineSettings())); + connect(&deintFineSetDialog, SIGNAL(requestFineCurrent()), L2B_PCM16X0_worker, SLOT(requestCurrentFineSettings())); + connect(&deintFineSetDialog, SIGNAL(setUseECC(bool)), L2B_PCM16X0_worker, SLOT(setFineUseECC(bool))); + connect(&deintFineSetDialog, SIGNAL(setMaskSeams(bool)), L2B_PCM16X0_worker, SLOT(setFineMaskSeams(bool))); + connect(&deintFineSetDialog, SIGNAL(setBrokeMask(uint8_t)), L2B_PCM16X0_worker, SLOT(setFineBrokeMask(uint8_t))); } else if(set_pcm_type==LIST_TYPE_STC007) { - connect(L2B_STC007_worker, SIGNAL(guiUpdFineMaxUnch14(uint8_t)), deintFineSetDialog, SLOT(newMaxUnchecked14(uint8_t))); - connect(L2B_STC007_worker, SIGNAL(guiUpdFineMaxUnch16(uint8_t)), deintFineSetDialog, SLOT(newMaxUnchecked16(uint8_t))); - connect(L2B_STC007_worker, SIGNAL(guiUpdFineUseECC(bool)), deintFineSetDialog, SLOT(newUseECC(bool))); - connect(L2B_STC007_worker, SIGNAL(guiUpdFineTopLineFix(bool)), deintFineSetDialog, SLOT(newInsertLine(bool))); - connect(L2B_STC007_worker, SIGNAL(guiUpdFineMaskSeams(bool)), deintFineSetDialog, SLOT(newMaskSeams(bool))); - connect(L2B_STC007_worker, SIGNAL(guiUpdFineBrokeMask(uint8_t)), deintFineSetDialog, SLOT(newBrokeMask(uint8_t))); + connect(L2B_STC007_worker, SIGNAL(guiUpdFineMaxUnch14(uint8_t)), &deintFineSetDialog, SLOT(newMaxUnchecked14(uint8_t))); + connect(L2B_STC007_worker, SIGNAL(guiUpdFineMaxUnch16(uint8_t)), &deintFineSetDialog, SLOT(newMaxUnchecked16(uint8_t))); + connect(L2B_STC007_worker, SIGNAL(guiUpdFineUseECC(bool)), &deintFineSetDialog, SLOT(newUseECC(bool))); + connect(L2B_STC007_worker, SIGNAL(guiUpdFineTopLineFix(bool)), &deintFineSetDialog, SLOT(newInsertLine(bool))); + connect(L2B_STC007_worker, SIGNAL(guiUpdFineMaskSeams(bool)), &deintFineSetDialog, SLOT(newMaskSeams(bool))); + connect(L2B_STC007_worker, SIGNAL(guiUpdFineBrokeMask(uint8_t)), &deintFineSetDialog, SLOT(newBrokeMask(uint8_t))); - connect(deintFineSetDialog, SIGNAL(setFineDefaults()), L2B_STC007_worker, SLOT(setDefaultFineSettings())); - connect(deintFineSetDialog, SIGNAL(requestFineCurrent()), L2B_STC007_worker, SLOT(requestCurrentFineSettings())); - connect(deintFineSetDialog, SIGNAL(setMaxUnchecked14(uint8_t)), L2B_STC007_worker, SLOT(setFineMaxUnch14(uint8_t))); - connect(deintFineSetDialog, SIGNAL(setMaxUnchecked16(uint8_t)), L2B_STC007_worker, SLOT(setFineMaxUnch16(uint8_t))); - connect(deintFineSetDialog, SIGNAL(setUseECC(bool)), L2B_STC007_worker, SLOT(setFineUseECC(bool))); - connect(deintFineSetDialog, SIGNAL(setInsertLine(bool)), L2B_STC007_worker, SLOT(setFineTopLineFix(bool))); - connect(deintFineSetDialog, SIGNAL(setMaskSeams(bool)), L2B_STC007_worker, SLOT(setFineMaskSeams(bool))); - connect(deintFineSetDialog, SIGNAL(setBrokeMask(uint8_t)), L2B_STC007_worker, SLOT(setFineBrokeMask(uint8_t))); + connect(&deintFineSetDialog, SIGNAL(setFineDefaults()), L2B_STC007_worker, SLOT(setDefaultFineSettings())); + connect(&deintFineSetDialog, SIGNAL(requestFineCurrent()), L2B_STC007_worker, SLOT(requestCurrentFineSettings())); + connect(&deintFineSetDialog, SIGNAL(setMaxUnchecked14(uint8_t)), L2B_STC007_worker, SLOT(setFineMaxUnch14(uint8_t))); + connect(&deintFineSetDialog, SIGNAL(setMaxUnchecked16(uint8_t)), L2B_STC007_worker, SLOT(setFineMaxUnch16(uint8_t))); + connect(&deintFineSetDialog, SIGNAL(setUseECC(bool)), L2B_STC007_worker, SLOT(setFineUseECC(bool))); + connect(&deintFineSetDialog, SIGNAL(setInsertLine(bool)), L2B_STC007_worker, SLOT(setFineTopLineFix(bool))); + connect(&deintFineSetDialog, SIGNAL(setMaskSeams(bool)), L2B_STC007_worker, SLOT(setFineMaskSeams(bool))); + connect(&deintFineSetDialog, SIGNAL(setBrokeMask(uint8_t)), L2B_STC007_worker, SLOT(setFineBrokeMask(uint8_t))); } - - deintFineSetDialog->exec(); - deintFineSetDialog->deleteLater(); + deintFineSetDialog.exec(); + //deintFineSetDialog->deleteLater(); } //------------------------ Receive request for fine settings reset from video processor fine settings dialog. @@ -1748,9 +1788,10 @@ void MainWindow::showVisSource(bool is_checked) connect(VIN_worker, SIGNAL(newLine(VideoLine)), renderSource, SLOT(renderNewLine(VideoLine))); } connect(VIN_worker, SIGNAL(frameDecoded(uint32_t)), renderSource, SLOT(finishNewFrame(uint32_t))); - connect(renderSource, SIGNAL(newFrame(QPixmap,uint32_t)), visuSource, SLOT(drawFrame(QPixmap,uint32_t))); + connect(renderSource, SIGNAL(newFrame(QImage,uint32_t)), visuSource, SLOT(drawFrame(QImage,uint32_t))); + connect(visuSource, SIGNAL(readyToDraw()), renderSource, SLOT(displayIsReady())); - vis_thread->start(); + vis_thread->start(QThread::LowPriority); } else if(visuSource!=NULL) { @@ -1809,9 +1850,10 @@ void MainWindow::showVisBin(bool is_checked) renderBin->setLineCount(FrameAsmDescriptor::VID_UNKNOWN); connect(this, SIGNAL(retransmitBinLine(STC007Line)), renderBin, SLOT(renderNewLine(STC007Line))); } - connect(renderBin, SIGNAL(newFrame(QPixmap,uint32_t)), visuBin, SLOT(drawFrame(QPixmap,uint32_t))); + connect(renderBin, SIGNAL(newFrame(QImage,uint32_t)), visuBin, SLOT(drawFrame(QImage,uint32_t))); + connect(visuBin, SIGNAL(readyToDraw()), renderBin, SLOT(displayIsReady())); - vis_thread->start(); + vis_thread->start(QThread::LowPriority); } else if(visuBin!=NULL) { @@ -1869,9 +1911,10 @@ void MainWindow::showVisAssembled(bool is_checked) renderAssembled->startSTC007NTSCFrame(); connect(this, SIGNAL(retransmitAsmLine(STC007Line)), renderAssembled, SLOT(renderNewLine(STC007Line))); } - connect(renderAssembled, SIGNAL(newFrame(QPixmap,uint32_t)), visuAssembled, SLOT(drawFrame(QPixmap,uint32_t))); + connect(renderAssembled, SIGNAL(newFrame(QImage,uint32_t)), visuAssembled, SLOT(drawFrame(QImage,uint32_t))); + connect(visuAssembled, SIGNAL(readyToDraw()), renderAssembled, SLOT(displayIsReady())); - vis_thread->start(); + vis_thread->start(QThread::LowPriority); } else if(visuAssembled!=NULL) { @@ -1929,9 +1972,10 @@ void MainWindow::showVisBlocks(bool is_checked) renderBlocks->startSTC007DBFrame(); connect(this, SIGNAL(retransmitPCMDataBlock(STC007DataBlock)), renderBlocks, SLOT(renderNewBlock(STC007DataBlock))); } - connect(renderBlocks, SIGNAL(newFrame(QPixmap,uint32_t)), visuBlocks, SLOT(drawFrame(QPixmap,uint32_t))); + connect(renderBlocks, SIGNAL(newFrame(QImage,uint32_t)), visuBlocks, SLOT(drawFrame(QImage,uint32_t))); + connect(visuBlocks, SIGNAL(readyToDraw()), renderBlocks, SLOT(displayIsReady())); - vis_thread->start(); + vis_thread->start(QThread::LowPriority); } else if(visuBlocks!=NULL) { @@ -1978,7 +2022,7 @@ void MainWindow::reopenVisSource() } } -//------------------------ Re-open all vizualization windows +//------------------------ Re-open all vizualization windows. void MainWindow::reopenVisualizers() { reopenVisSource(); @@ -2015,7 +2059,7 @@ void MainWindow::updateSetMainLog() setDILogMode(); } -//------------------------ Save settings for [vin_processor] module. +//------------------------ Save settings for [VideoInFFMPEG] module. void MainWindow::updateSetVIPLog() { QSettings settings_hdl(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); @@ -2028,7 +2072,7 @@ void MainWindow::updateSetVIPLog() setVIPLogMode(); } -//------------------------ Save settings for [videotodigital] and [Binarizer] modules. +//------------------------ Save settings for [VideoToDigital] and [Binarizer] modules. void MainWindow::updateSetLBLog() { QSettings settings_hdl(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); @@ -2044,7 +2088,7 @@ void MainWindow::updateSetLBLog() setLBLogMode(); } -//------------------------ Save settings for [stc007datastitcher] and [stc007deinterleaver] modules. +//------------------------ Save settings for [xDataStitcher] and [xDeinterleaver] modules. void MainWindow::updateSetDILog() { QSettings settings_hdl(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); @@ -2063,7 +2107,7 @@ void MainWindow::updateSetDILog() setDILogMode(); } -//------------------------ Save settings for [audioprocessor] and [stc007towav] modules. +//------------------------ Save settings for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. void MainWindow::updateSetAPLog() { QSettings settings_hdl(QSettings::IniFormat, QSettings::UserScope, APP_ORG_NAME, APP_INI_NAME); @@ -2088,7 +2132,7 @@ void MainWindow::clearMainPLog() updateSetMainLog(); } -//------------------------ Turn off logging for [vin_processor] module. +//------------------------ Turn off logging for [VideoInFFMPEG] module. void MainWindow::clearVIPLog() { // Clear marks. @@ -2100,7 +2144,7 @@ void MainWindow::clearVIPLog() updateSetVIPLog(); } -//------------------------ Turn off logging for [videotodigital] and [Binarizer] modules. +//------------------------ Turn off logging for [VideoToDigital] and [Binarizer] modules. void MainWindow::clearLBLog() { // Clear marks. @@ -2115,7 +2159,7 @@ void MainWindow::clearLBLog() updateSetLBLog(); } -//------------------------ Turn off logging for [stc007datastitcher] and [stc007deinterleaver] modules. +//------------------------ Turn off logging for [xDataStitcher] and [xDeinterleaver] modules. void MainWindow::clearDILog() { // Clear marks. @@ -2133,7 +2177,7 @@ void MainWindow::clearDILog() updateSetDILog(); } -//------------------------ Turn off debug logging for [audioprocessor] and [stc007towav] modules. +//------------------------ Turn off debug logging for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. void MainWindow::clearAPLog() { // Clear marks. @@ -2157,7 +2201,7 @@ void MainWindow::clearAllLogging() clearAPLog(); } -//------------------------ +//------------------------ React on video decoder asking for a source. void MainWindow::playerNoSource() { // Open dialog for selecting a file. @@ -2176,7 +2220,7 @@ void MainWindow::playerNoSource() loadVideo(); } -//------------------------ +//------------------------ React on video decoder loading a new source. void MainWindow::playerLoaded(QString in_path) { ui->lblFileName->setText(in_path); @@ -2192,7 +2236,7 @@ void MainWindow::playerLoaded(QString in_path) ui->cbxWaveSave->setEnabled(true); } -//------------------------ +//------------------------ React on video decoder starting playback. void MainWindow::playerStarted(uint32_t in_frames_total) { stat_total_frame_cnt = in_frames_total; @@ -2209,7 +2253,7 @@ void MainWindow::playerStarted(uint32_t in_frames_total) v_decoder_state = VDEC_PLAY; } -//------------------------ +//------------------------ React on video decoder stopping playback. void MainWindow::playerStopped() { ui->btnOpen->setEnabled(true); @@ -2225,7 +2269,7 @@ void MainWindow::playerStopped() v_decoder_state = VDEC_STOP; } -//------------------------ +//------------------------ React on video decoder pausing playback. void MainWindow::playerPaused() { ui->btnOpen->setEnabled(true); @@ -2241,7 +2285,7 @@ void MainWindow::playerPaused() v_decoder_state = VDEC_PAUSE; } -//------------------------ Catch video input error and reset playback. +//------------------------ React on video decoder error. void MainWindow::playerError(QString error_text) { ui->btnOpen->setEnabled(true); @@ -2259,7 +2303,7 @@ void MainWindow::playerError(QString error_text) this->displayErrorMessage(error_text); } -//------------------------ Update LIVE playback indicator. +//------------------------ React on live playback state. void MainWindow::livePBUpdate(bool flag) { if(flag==false) @@ -2272,21 +2316,6 @@ void MainWindow::livePBUpdate(bool flag) } } -//------------------------ Check essential threads. -void MainWindow::checkThreads() -{ - if((conv_V2D->isRunning()==false)||(conv_V2D->isFinished()!=false)) - { - qWarning()<start(); - } - if((conv_L2B_STC007->isRunning()==false)||(conv_L2B_STC007->isFinished()!=false)) - { - qWarning()<start(); - } -} - //------------------------ Update GUI counters and bars with data. void MainWindow::updateGUIByTimer() { @@ -2338,34 +2367,16 @@ void MainWindow::updateGUIByTimer() ui->lcdBadStitch->display((int)stat_bad_stitch_cnt); ui->lcdPCorr->display((int)stat_p_fix_cnt); ui->lcdQCorr->display((int)stat_q_fix_cnt); - ui->lcdDebug->display((int)stat_cwd_fix_cnt); + ui->lcdCWDCorr->display((int)stat_cwd_fix_cnt); ui->lcdBroken->display((int)stat_broken_block_cnt); ui->lcdDropout->display((int)stat_drop_block_cnt); ui->lcdSampleDrops->display((int)stat_drop_sample_cnt); - ui->lcdMute->display((int)stat_mute_cnt); ui->lcdMask->display((int)stat_mask_cnt); ui->lcdProcessedFrames->display((int)stat_processed_frame_cnt); // Update VU-meters. ui->pgrVULeft->setValue(vu_left); ui->pgrVURight->setValue(vu_right); - // Decay VU-meters. - if(vu_left>6) - { - vu_left -= 6; - } - else if(vu_left>0) - { - vu_left--; - } - if(vu_right>6) - { - vu_right -= 6; - } - else if(vu_right>0) - { - vu_right--; - } // Update queue fills. size_t buf_size; @@ -2584,10 +2595,22 @@ void MainWindow::updatePCM16x0FrameData() void MainWindow::updateSTC007FrameData() { uint16_t field_imbalance; - QString odd_number_str, even_number_str; + QString frame_num, odd_number_str, even_number_str; CoordinatePair data_coord; // Update frame number. - ui->edtSTC007FrameNo->setText(QString::number(frame_asm_stc007.frame_number, 10)); + frame_num = QString::number(frame_asm_stc007.frame_number, 10); + if(frame_asm_stc007.isAddressSet()!=false) + { + // Assemble index and time code string. + frame_num.sprintf("%u (Index: %02d, %02d:%02d:%02d.%02d)", + frame_asm_stc007.frame_number, + frame_asm_stc007.ctrl_index, + frame_asm_stc007.ctrl_hour, + frame_asm_stc007.ctrl_minute, + frame_asm_stc007.ctrl_second, + frame_asm_stc007.ctrl_field/2); + } + ui->edtSTC007FrameNo->setText(frame_num); // Update field order. if(frame_asm_stc007.isOrderSet()==false) { @@ -2816,60 +2839,67 @@ void MainWindow::updateSTC007FrameData() frame_asm_stc007.drawn = true; } -//------------------------ +//------------------------ Receive and retransmit binarized PCM-1 line. void MainWindow::receiveBinLine(PCM1Line in_line) { emit retransmitBinLine(in_line); } -//------------------------ +//------------------------ Receive and retransmit binarized PCM-16x0 sub-line. void MainWindow::receiveBinLine(PCM16X0SubLine in_line) { emit retransmitBinLine(in_line); } -//------------------------ +//------------------------ Receive and retransmit binarized STC-007 line. void MainWindow::receiveBinLine(STC007Line in_line) { emit retransmitBinLine(in_line); } -//------------------------ +//------------------------ Receive and retransmit PCM-1 sub-line from re-assembled frame. void MainWindow::receiveAsmLine(PCM1SubLine in_line) { emit retransmitAsmLine(in_line); } -//------------------------ +//------------------------ Receive and retransmit PCM-16x0 sub-line from re-assembled frame. void MainWindow::receiveAsmLine(PCM16X0SubLine in_line) { emit retransmitAsmLine(in_line); } -//------------------------ +//------------------------ Receive and retransmit STC-007 line from re-assembled frame. void MainWindow::receiveAsmLine(STC007Line in_line) { emit retransmitAsmLine(in_line); } -//------------------------ +//------------------------ Receive and retransmit PCM-1 data block after deinterleave. void MainWindow::receivePCMDataBlock(PCM1DataBlock in_block) { emit retransmitPCMDataBlock(in_block); } -//------------------------ +//------------------------ Receive and retransmit PCM-16x0 data block after deinterleave. void MainWindow::receivePCMDataBlock(PCM16X0DataBlock in_block) { emit retransmitPCMDataBlock(in_block); } -//------------------------ +//------------------------ Receive and retransmit STC-007 data block after deinterleave. void MainWindow::receivePCMDataBlock(STC007DataBlock in_block) { emit retransmitPCMDataBlock(in_block); } +//------------------------ Receive VU levels for displaying. +void MainWindow::receiveVUMeters(uint8_t in_l, uint8_t in_r) +{ + vu_left = in_l; + vu_right = in_r; +} + //------------------------ Update stats for debug bar. void MainWindow::updateDebugBar(quint64 in_stat) { @@ -2897,62 +2927,20 @@ void MainWindow::updateDebugBar(quint64 in_stat) ui->pgrDebug->setValue(stat_summ); } -//------------------------ Update stats after LB has finished a line and provided spent time count. -void MainWindow::updateStatsVideoLineTime(uint32_t line_time) -{ - stat_vlines_time_per_frame += line_time; - if(stat_min_vip_time>line_time) - { - stat_min_vip_time = line_time; - } - if(stat_max_vip_timestat_total_frame_cnt) { + // Correct total frame counter. stat_total_frame_cnt = stat_read_frame_cnt; } - - QString log_line; - if(lines_per_video!=0) - { - log_line = "Frame "+QString::number(frame_no)+" split to "+QString::number(lines_per_video)+" lines by " - +QString::number(stat_vlines_time_per_frame)+" us ("+QString::number(stat_vlines_time_per_frame/lines_per_video)+" us per line)"; - } - else - { - log_line = "Frame "+QString::number(frame_no); - } - //log_line = "Lines from frame "+QString::number(frame_no)+" added by "+QString::number(in_time)+" us"; - // Output some debug info. - if((log_level&LOG_PROCESS)!=0) - { - qInfo()<<"[M]"<line_time) - { - stat_min_bin_time = line_time; - } - if(stat_max_bin_time stat_tracking_arr; FrameBinDescriptor stat_video_tracking; - uint64_t stat_vlines_time_per_frame; - uint32_t stat_min_vip_time; - uint32_t stat_max_vip_time; - uint64_t stat_lines_time_per_frame; - uint32_t stat_min_bin_time; - uint32_t stat_max_bin_time; uint16_t stat_lines_per_frame; uint64_t stat_blocks_time_per_frame; uint32_t stat_min_di_time; @@ -307,7 +300,6 @@ class MainWindow : public QMainWindow uint32_t stat_broken_block_cnt; uint32_t stat_drop_block_cnt; uint32_t stat_drop_sample_cnt; - uint32_t stat_mute_cnt; uint32_t stat_mask_cnt; uint32_t stat_processed_frame_cnt; uint32_t stat_line_cnt; @@ -319,29 +311,29 @@ class MainWindow : public QMainWindow ~MainWindow(); private: - void moveEvent(QMoveEvent *event); - void resizeEvent(QResizeEvent *event); - void closeEvent(QCloseEvent *event); + void moveEvent(QMoveEvent *event); // Main window was moved. + void resizeEvent(QResizeEvent *event); // Main window was resized. + void closeEvent(QCloseEvent *event); // Application is about to close. QString generateTranslationPath(QString in_locale); QStringList getTranslationList(); void updateGUILangList(); void setGUILanguage(QString in_locale, bool suppress = false); // Select UI language. // Update settings for modules. - void setVIPOptions(); // Set options for [vin_processor] module. - void setLBOptions(); // Set options for [videotodigital] and [stc007binarizer] modules. - void setDIOptions(); // Set options for [stc007datastitcher] and [stc007deinterleaver] modules. - void setAPOptions(); // Set options for [audioprocessor] and [stc007towav] modules. + void setVIPOptions(); // Set options for [VideoInFFMPEG] module. + void setLBOptions(); // Set options for [VideoToDigital] and [Binarizer] modules. + void setDIOptions(); // Set options for [xDataStitcher] and [xDeinterleaver] modules. + void setAPOptions(); // Set options for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. // Update logging settings. void setMainLogMode(); // Set debug logging mode for main module. - void setVIPLogMode(); // Set debug logging mode for [vin_processor] module. - void setLBLogMode(); // Set debug logging mode for [videotodigital] and [stc007binarizer] modules. - void setDILogMode(); // Set debug logging mode for [stc007datastitcher] and [stc007deinterleaver] modules. - void setAPLogMode(); // Set debug logging mode for [audioprocessor] and [stc007towav] modules. - - void disableGUIEvents(); // Disable comboboxes events to prevent switching settings to default while changing translation. - void enableGUIEvents(); // Re-enable comboboxes events after changing translation. - void applyGUISettings(); // Apply GUI settings to the decoder. + void setVIPLogMode(); // Set debug logging mode for [VideoInFFMPEG] module. + void setLBLogMode(); // Set debug logging mode for [VideoToDigital] and [Binarizer] modules. + void setDILogMode(); // Set debug logging mode for [xDataStitcher] and [xDeinterleaver] modules. + void setAPLogMode(); // Set debug logging mode for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. + + void disableGUIEvents(); // Disable GUI events to prevent switching settings to default while changing translation. + void enableGUIEvents(); // Re-enable GUI events after changing translation. + void applyGUISettings(); // Apply GUI settings to different modules. void readGUISettings(); // Read settings into GUI. CoordinatePair getCoordByFrameNo(uint32_t); // Find and return coordinates from video tracking history. @@ -349,33 +341,30 @@ class MainWindow : public QMainWindow private slots: //void dbgSlot(int); - void updateWindowPosition(); - void displayErrorMessage(QString); + void exitAction(); // Exit application. + void setLang(QAction *); // User request to set GUI language. + void updateWindowPosition(); // Save new main window position and size in setting storage. + void displayErrorMessage(QString); // Display window with an error, stop playback. - void setLang(QAction *); - - void playVideo(); - void pauseVideo(); - void loadVideo(); - void unloadSource(); - void loadPicture(); - void exitAction(); + void loadVideo(); // User request to open a new source. + void unloadSource(); // User request to close the source and free resources. + void usrPlayStop(); // User request to start/stop video playback/decode. + void usrPause(); // User request to pause video playback/decode. // GUI selection reactions. void updateGUISettings(); // Save settings for GUI options. void clearStat(); // Clear decoder stats. + void sliderDisplayUpdate(); // Main menu reactions. - void resetOptDecoder(); - void resetVisPositions(); - void resetFull(); - + void resetOptDecoder(); // Confirm and reset decoder settings. + void resetVisPositions(); // Confirm and reset visualizer windows positions. + void resetFull(); // Confirm and reset all settings. void showAbout(); // Display "About" window. void showCaptureSelector(); // Display video capture selection dialog. void showVidInFineSettings(); // Display video processor fine settings dialog. void showBinFineSettings(); // Display binarizator fine settings dialog. void showDeintFineSettings(); // Display deinterleaver fine settings dialog. - void setDefaultFineSettings(); // Receive request for fine settings reset from video processor fine settings dialog. void requestCurrentFineSettings(); // Receive request for fine settings from video processor fine settings dialog. void setFineDrawDeint(bool); @@ -392,15 +381,15 @@ private slots: void reopenVisualizers(); // Re-open all vizualization windows. void updateSetMainLog(); // Save settings for logging mode for main module. - void updateSetVIPLog(); // Save settings for [vin_processor] module. - void updateSetLBLog(); // Save settings for [videotodigital] and [stc007binarizer] modules. - void updateSetDILog(); // Save settings for [stc007datastitcher] and [stc007deinterleaver] modules. - void updateSetAPLog(); // Save settings for [audioprocessor] and [stc007towav] modules. + void updateSetVIPLog(); // Save settings for [VideoInFFMPEG] module. + void updateSetLBLog(); // Save settings for [VideoToDigital] and [Binarizer] modules. + void updateSetDILog(); // Save settings for [xDataStitcher] and [xDeinterleaver] modules. + void updateSetAPLog(); // Save settings for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. void clearMainPLog(); // Turn off debug logging for main module. - void clearVIPLog(); // Turn off debug logging for [vin_processor] module. - void clearLBLog(); // Turn off debug logging for [videotodigital] and [stc007binarizer] modules. - void clearDILog(); // Turn off debug logging for [stc007datastitcher] and [stc007deinterleaver] modules. - void clearAPLog(); // Turn off debug logging for [audioprocessor] and [stc007towav] modules. + void clearVIPLog(); // Turn off debug logging for [VideoInFFMPEG] module. + void clearLBLog(); // Turn off debug logging for [VideoToDigital] and [stc007binarizer] modules. + void clearDILog(); // Turn off debug logging for [xDataStitcher] and [xDeinterleaver] modules. + void clearAPLog(); // Turn off debug logging for [AudioProcessor], [SamplesToAudio] and [SamplesToWAV] modules. void clearAllLogging(); // Turn off all debug logging. // Player state reactions. @@ -412,42 +401,35 @@ private slots: void playerError(QString); // React on video decoder error. void livePBUpdate(bool); // React on live playback state. - // Timer reactions. - void checkThreads(); // Check if all threads are alive. - - void updateGUIByTimer(); + void updateGUIByTimer(); // Update GUI counters and bars with data. void updatePCM1FrameData(); // Update PCM-1 frame assembling data. void updatePCM16x0FrameData(); // Update PCM-16x0 frame assembling data. void updateSTC007FrameData(); // Update STC-007 frame assembling data. // Buffered receivers for visualizers. - void receiveBinLine(PCM1Line); - void receiveBinLine(PCM16X0SubLine); - void receiveBinLine(STC007Line); - void receiveAsmLine(PCM1SubLine); - void receiveAsmLine(PCM16X0SubLine); - void receiveAsmLine(STC007Line); - void receivePCMDataBlock(PCM1DataBlock); - void receivePCMDataBlock(PCM16X0DataBlock); - void receivePCMDataBlock(STC007DataBlock); + void receiveBinLine(PCM1Line); // Receive and retransmit binarized PCM-1 line. + void receiveBinLine(PCM16X0SubLine); // Receive and retransmit binarized PCM-16x0 sub-line. + void receiveBinLine(STC007Line); // Receive and retransmit binarized STC-007 line. + void receiveAsmLine(PCM1SubLine); // Receive and retransmit PCM-1 sub-line from re-assembled frame. + void receiveAsmLine(PCM16X0SubLine); // Receive and retransmit PCM-16x0 sub-line from re-assembled frame. + void receiveAsmLine(STC007Line); // Receive and retransmit STC-007 line from re-assembled frame. + void receivePCMDataBlock(PCM1DataBlock); // Receive and retransmit PCM-1 data block after deinterleave. + void receivePCMDataBlock(PCM16X0DataBlock); // Receive and retransmit PCM-16x0 data block after deinterleave. + void receivePCMDataBlock(STC007DataBlock); // Receive and retransmit STC-007 data block after deinterleave. + void receiveVUMeters(uint8_t, uint8_t); // Receive VU levels for displaying. // Stats gathering reactions. void updateDebugBar(quint64); - void updateStatsVideoLineTime(uint32_t);// Update stats after VIP has finished a line and provided spent time count. void updateStatsVIPFrame(uint32_t); // Update stats after VIP has read a frame. void updateStatsVideoTracking(FrameBinDescriptor); // Update stats after VIP has spliced a frame. void updateStatsDroppedFrame(); // Update stats with new value for dropped frames. - void updateStatsLineTime(unsigned int); // Update stats after LB has finished a line and provided spent time count. void updateStatsFrameAsm(FrameAsmPCM1); // Update stats and video processor with new trim settings. void updateStatsFrameAsm(FrameAsmPCM16x0); // Update stats and video processor with new trim settings. void updateStatsFrameAsm(FrameAsmSTC007); // Update stats and video processor with new trim settings. - void updateStatsMutes(uint16_t); // Update stats with new value for muted samples. void updateStatsMaskes(uint16_t); // Update stats with new value for masked samples. void updateStatsBlockTime(STC007DataBlock); // Update stats after DI has finished a data block and provided spent time count. void updateStatsDIFrame(uint32_t); // Update stats after DI has finished a frame. - void updateVU(PCMSamplePair); - // Self-test start and result reactions. void testStartCRCC(); // Perform internal test of CRCC within PCM line. void testStartECC(); // Perform internal test of ECC within PCM data block. @@ -474,6 +456,9 @@ private slots: // Signals for deinterleaver (line-to-block) module. void newL2BLogLevel(uint16_t); // Send new logging level for L2B thread. void newPCM1FieldOrder(uint8_t); // Send new PCM-1 field order setting. + void newPCM1AutoOffset(bool); // Send new PCM-1 auto offset setting. + void newPCM1OddOffset(int8_t); // Send new PCM-1 odd line offset setting. + void newPCM1EvenOffset(int8_t); // Send new PCM-1 even line offset setting. void newPCM16x0Format(uint8_t); // Send new PCM-1630 format setting. void newPCM16x0FieldOrder(uint8_t); // Send new PCM-16x0 field order setting. void newPCM16x0PCorrection(bool); // Send new PCM-16x0 P-code correction setting. @@ -508,10 +493,10 @@ private slots: void newFineReset(); void guiUpdFineDrawDeint(bool); - void doPlayUnload(); - void doPlayStart(); - void doPlayPause(); - void doPlayStop(); + void doPlayUnload(); // Request unload/close source to video input processor. + void doPlayStart(); // Request start playback to video input processor. + void doPlayPause(); // Request pause playback to video input processor. + void doPlayStop(); // Request stop playback to video input processor. }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index 0edb87c..dfd04b9 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 - 1108 + 1142 680 @@ -404,7 +404,7 @@ - 0 + 200 7 @@ -413,6 +413,12 @@ 3 + + Индикатор уровня аудио, левый канал + + + Индикатор уровня аудио, левый канал + 255 @@ -440,7 +446,7 @@ - 0 + 200 7 @@ -449,6 +455,12 @@ 3 + + Индикатор уровня аудио, правый канал + + + Индикатор уровня аудио, правый канал + 255 @@ -515,35 +527,22 @@ 0 - - + + - + 0 0 - - Вставка сверху: - - - - - - - false + + Смещение (в строках) данных от верха чётного поля - - - 0 - 0 - + + Смещение (в строках) данных от верха чётного поля - - - 0 - 25 - + + Чётное поле: @@ -555,6 +554,12 @@ 0 + + + 120 + 0 + + Порядок полей в кадрах исходного видео @@ -566,13 +571,13 @@ - + true - + 0 0 @@ -604,36 +609,234 @@ - - + + - + 0 0 + + Смещение (в строках) данных от верха нечётного поля + + + Смещение (в строках) данных от верха нечётного поля + + + -120 + + + 120 + + + false + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + + 0 + 0 + + + + Смещение (в строках) данных от верха чётного поля + + + Смещение (в строках) данных от верха чётного поля + + + -120 + + + 120 + + + -1 + + + false + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + + 0 + 0 + + + + false + + + Qt::NoFocus + + + false + + + Смещение (в строках) данных от верха чётного поля + + + Смещение (в строках) данных от верха чётного поля + - Вставка снизу: + 0 + + + 5 + + + Qt::AlignCenter + + + true - - + + + + 0 + 0 + + + + Смещение (в строках) данных от верха нечётного поля + + + Смещение (в строках) данных от верха нечётного поля + + + Нечётное поле: + + + + + + + + 0 + 0 + + + false + + Qt::NoFocus + + + false + + + Смещение (в строках) данных от верха нечётного поля + + + Смещение (в строках) данных от верха нечётного поля + + + 0 + + + 5 + + + Qt::AlignCenter + + + true + + + + + - + 0 0 - 0 - 25 + 10 + 0 + + + + + 30 + 16777215 + + >> + + + true + + + false + + + + + + + + 0 + 0 + + + + Параметры смещения данных в полях по вертикали + + + Параметры смещения данных в полях по вертикали + + + Смещение сверху: + + + + + + + + 0 + 0 + + + + Попытаться автоматически выровнять данные в полях по высоте (результат не гарантирован) + + + Попытаться автоматически выровнять данные в полях по высоте (результат не гарантирован) + + + Автоматически по содержимому + + + true + @@ -779,6 +982,12 @@ 0 + + + 120 + 0 + + Порядок полей в кадрах исходного видео @@ -993,6 +1202,12 @@ 0 + + + 120 + 0 + + Порядок полей в кадрах исходного видео @@ -1049,9 +1264,6 @@ - - false - 0 @@ -1420,7 +1632,7 @@ - 100 + 120 0 @@ -1512,10 +1724,10 @@ - Применение коррекции АЧХ + Функционал ещё не готов - Применение коррекции АЧХ + Функционал ещё не готов 0 @@ -1549,7 +1761,7 @@ QFrame::Plain - 2 + 0 @@ -2047,6 +2259,12 @@ 0 + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + Координаты: @@ -2063,6 +2281,12 @@ Qt::NoFocus + + Усреднённые по кадру координаты начала данных (в пикселях) + + + Усреднённые по кадру координаты начала данных (в пикселях) + true @@ -2088,6 +2312,12 @@ Qt::NoFocus + + Усреднённые по кадру координаты конца данных (в пикселях) + + + Усреднённые по кадру координаты конца данных (в пикселях) + true @@ -2650,6 +2880,12 @@ 0 + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + Координаты: @@ -2666,6 +2902,12 @@ Qt::NoFocus + + Усреднённые по кадру координаты начала данных (в пикселях) + + + Усреднённые по кадру координаты начала данных (в пикселях) + true @@ -2691,6 +2933,12 @@ Qt::NoFocus + + Усреднённые по кадру координаты конца данных (в пикселях) + + + Усреднённые по кадру координаты конца данных (в пикселях) + true @@ -2993,6 +3241,12 @@ 0 + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + + + Усреднённые по кадру координаты данных по горизонтали (в пикселях) + Координаты: @@ -3009,6 +3263,12 @@ Qt::NoFocus + + Усреднённые по кадру координаты начала данных (в пикселях) + + + Усреднённые по кадру координаты начала данных (в пикселях) + true @@ -3034,6 +3294,12 @@ Qt::NoFocus + + Усреднённые по кадру координаты конца данных (в пикселях) + + + Усреднённые по кадру координаты конца данных (в пикселях) + true @@ -4006,7 +4272,7 @@ QFrame::Sunken - 7 + 8 QLCDNumber::Flat @@ -4099,7 +4365,7 @@ QFrame::Sunken - 7 + 8 QLCDNumber::Flat @@ -4221,7 +4487,7 @@ - + @@ -4319,7 +4585,7 @@ Q-коррекций: - + Число блоков данных, не имеющих ошибок по CRC, но не прошедшие проверку по P и Q словам @@ -4361,7 +4627,7 @@ Q-коррекций: - + @@ -4380,6 +4646,76 @@ Q-коррекций: + + + + + + + + + 0 + 170 + 0 + + + + + + + + + 0 + 170 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + + Число блоков данных, в которых успешно исправлены ошибки с помощью Cross-Word Decoding + + + Число блоков данных, в которых успешно исправлены ошибки с помощью Cross-Word Decoding + + + QFrame::Sunken + + + 8 + + + QLCDNumber::Flat + + + + + + + Число блоков данных, в которых успешно исправлены ошибки с помощью Cross-Word Decoding + + + Число блоков данных, в которых успешно исправлены ошибки с помощью Cross-Word Decoding + + + Успешных +CWD-коррекций: + + + @@ -4631,79 +4967,6 @@ Q-коррекций: - - - - Число аудио-отсчётов, в которых заглушено выпадение - - - Число аудио-отсчётов, в которых заглушено выпадение - - - Заглушено -аудио-отсчётов: - - - true - - - - - - - - - - - - 190 - 130 - 0 - - - - - - - - - 190 - 130 - 0 - - - - - - - - - 210 - 210 - 210 - - - - - - - - Число аудио-отсчётов, в которых заглушено выпадение - - - Число аудио-отсчётов, в которых заглушено выпадение - - - QFrame::Sunken - - - 8 - - - QLCDNumber::Flat - - - @@ -4711,6 +4974,9 @@ Q-коррекций: + + false + Отладка: время выполнения @@ -4769,7 +5035,7 @@ Q-коррекций: 0 0 - 1108 + 1142 21 @@ -5543,12 +5809,13 @@ Q-коррекций: btnPlay cbxFrameStep btnPause - btnStatReset lbxBinQuality lbxPCMType lbxPCM1FieldOrder - spbPCM1BottomPad - spbPCM1TopPad + cbxPCM1Offset + sldPCM1OddOfs + btnPCM1OfsSync + sldPCM1EvenOfs lbxPCM16x0Format lbxPCM16x0FieldOrder lbxPCM16x0ECC @@ -5561,6 +5828,7 @@ Q-коррекций: lbxSTC007SampleRate lbxDeemphasis lbxDropAction + btnStatReset diff --git a/pcm16x0datastitcher.cpp b/pcm16x0datastitcher.cpp index 845bd4b..f03467f 100644 --- a/pcm16x0datastitcher.cpp +++ b/pcm16x0datastitcher.cpp @@ -36,7 +36,7 @@ void PCM16X0DataStitcher::setInputPointers(std::deque *in_pcmlin { if((in_pcmline==NULL)||(mtx_pcmline==NULL)) { - qWarning()< *out_pcmsa { if((out_pcmsamples==NULL)||(mtx_pcmsamples==NULL)) { - qWarning()< *fi } else { - qWarning()< *fi } else { - qWarning()<<"[L2B-16x0] Offset out-of-bounds in [PCM16X0DataStitcher::estimateBlockNumber()]:"< *field_bu if(field_buf==NULL) { - qWarning()<size()<(*f_size)) { - qWarning()< *field_bu #ifdef DI_EN_DBG_OUT if(suppress_log==false) { - qInfo()<<"[L2B-16x0] Not enough data in the field buffer in [PCM16X0DataStitcher::findSIPadding()], exiting..."; + qInfo()<<"[L2B-16x0] Not enough data in the field buffer, exiting..."; } #endif return DS_RET_NO_DATA; @@ -3537,7 +3537,7 @@ uint8_t PCM16X0DataStitcher::findEIDataAlignment(std::vector *fi else { // Error is too big. - qWarning()<STG_PAD_MAX) { #ifdef DI_EN_DBG_OUT - qWarning()< *fie } else { - qWarning()<size()<<", start index:"<size()<<", start index:"<isBlockValid(); + if(block_state==false) + { + word_left_fixed = word_right_fixed = false; + } + else + { + word_left_fixed = in_block->isWordCRCOk(PCM16X0DataBlock::SUBBLK_1, PCM16X0DataBlock::WORD_L); + word_right_fixed = in_block->isWordCRCOk(PCM16X0DataBlock::SUBBLK_1, PCM16X0DataBlock::WORD_R); + } word_left_state = in_block->isWordValid(PCM16X0DataBlock::SUBBLK_1, PCM16X0DataBlock::WORD_L); word_right_state = in_block->isWordValid(PCM16X0DataBlock::SUBBLK_1, PCM16X0DataBlock::WORD_R); } @@ -4961,17 +4971,29 @@ void PCM16X0DataStitcher::outputDataBlock(PCM16X0DataBlock *in_block) // Data block deemed to be "broken", no data can be taken as valid. block_state = false; word_left_state = word_right_state = false; + word_left_fixed = word_right_fixed = false; } // Set data to [PCMSamplePair] object. sample_pair.setSamplePair(in_block->getSample(PCM16X0DataBlock::SUBBLK_1, PCM16X0DataBlock::WORD_L), in_block->getSample(PCM16X0DataBlock::SUBBLK_1, PCM16X0DataBlock::WORD_R), - block_state, block_state, word_left_state, word_right_state); + block_state, block_state, + word_left_state, word_right_state, + word_left_fixed, word_right_fixed); // Put sample pair in the output queue. out_samples->push_back(sample_pair); // Output L1+R1 samples. if(in_block->isDataBroken(PCM16X0DataBlock::SUBBLK_2)==false) { block_state = in_block->isBlockValid(); + if(block_state==false) + { + word_left_fixed = word_right_fixed = false; + } + else + { + word_left_fixed = in_block->isWordCRCOk(PCM16X0DataBlock::SUBBLK_2, PCM16X0DataBlock::WORD_L); + word_right_fixed = in_block->isWordCRCOk(PCM16X0DataBlock::SUBBLK_2, PCM16X0DataBlock::WORD_R); + } word_left_state = in_block->isWordValid(PCM16X0DataBlock::SUBBLK_2, PCM16X0DataBlock::WORD_L); word_right_state = in_block->isWordValid(PCM16X0DataBlock::SUBBLK_2, PCM16X0DataBlock::WORD_R); } @@ -4979,15 +5001,27 @@ void PCM16X0DataStitcher::outputDataBlock(PCM16X0DataBlock *in_block) { block_state = false; word_left_state = word_right_state = false; + word_left_fixed = word_right_fixed = false; } sample_pair.setSamplePair(in_block->getSample(PCM16X0DataBlock::SUBBLK_2, PCM16X0DataBlock::WORD_L), in_block->getSample(PCM16X0DataBlock::SUBBLK_2, PCM16X0DataBlock::WORD_R), - block_state, block_state, word_left_state, word_right_state); + block_state, block_state, + word_left_state, word_right_state, + word_left_fixed, word_right_fixed); out_samples->push_back(sample_pair); // Output L2+R2 samples. if(in_block->isDataBroken(PCM16X0DataBlock::SUBBLK_3)==false) { block_state = in_block->isBlockValid(); + if(block_state==false) + { + word_left_fixed = word_right_fixed = false; + } + else + { + word_left_fixed = in_block->isWordCRCOk(PCM16X0DataBlock::SUBBLK_3, PCM16X0DataBlock::WORD_L); + word_right_fixed = in_block->isWordCRCOk(PCM16X0DataBlock::SUBBLK_3, PCM16X0DataBlock::WORD_R); + } word_left_state = in_block->isWordValid(PCM16X0DataBlock::SUBBLK_3, PCM16X0DataBlock::WORD_L); word_right_state = in_block->isWordValid(PCM16X0DataBlock::SUBBLK_3, PCM16X0DataBlock::WORD_R); } @@ -4995,10 +5029,13 @@ void PCM16X0DataStitcher::outputDataBlock(PCM16X0DataBlock *in_block) { block_state = false; word_left_state = word_right_state = false; + word_left_fixed = word_right_fixed = false; } sample_pair.setSamplePair(in_block->getSample(PCM16X0DataBlock::SUBBLK_3, PCM16X0DataBlock::WORD_L), in_block->getSample(PCM16X0DataBlock::SUBBLK_3, PCM16X0DataBlock::WORD_R), - block_state, block_state, word_left_state, word_right_state); + block_state, block_state, + word_left_state, word_right_state, + word_left_fixed, word_right_fixed); out_samples->push_back(sample_pair); mtx_samples->unlock(); if(size_lock!=false) @@ -5040,7 +5077,7 @@ void PCM16X0DataStitcher::outputFileStop() size_t queue_size; if((out_samples==NULL)||(mtx_samples==NULL)) { - qWarning()<STG_CONVERT_MAX) { #ifdef DI_EN_DBG_OUT - qWarning()< *in_pcmline, QMutex { if((in_pcmline==NULL)||(mtx_pcmline==NULL)) { - qWarning()< *out_pcmsampl { if((out_pcmsamples==NULL)||(mtx_pcmsamples==NULL)) { - qWarning()<0) + { + frasm_f1.odd_top_data = 2*preset_odd_offset+1; + } + else + { + frasm_f1.odd_top_data = 1; + } + // Even field offset. + if(preset_even_offset>0) + { + frasm_f1.even_top_data = 2*preset_even_offset+2; + } + else + { + frasm_f1.even_top_data = 2; + } + } + // Cycle through the whole buffer. // (assuming that buffer starts on the first line of the frame) line_ind = 0; @@ -585,6 +610,7 @@ void PCM1DataStitcher::splitFrameToFields() { uint16_t line_ind, line_num; uint32_t ref_lvl_odd, ref_lvl_even, ref_lvl_odd_bad, ref_lvl_even_bad; + PCM1Line current_line; PCM1SubLine sub_temp; #ifdef DI_EN_DBG_OUT @@ -602,10 +628,11 @@ void PCM1DataStitcher::splitFrameToFields() // Cycle splitting frame buffer into 2 field buffers. while(line_ind=frasm_f1.even_top_data)&&(line_num<=frasm_f1.even_bottom_data)) { + // Check for stray header inside the data. + if(current_line.isServiceLine()!=false) + { + // Make this line invalid. + current_line.clear(); + } + // Cycle through sub-lines in one line. for(uint8_t sub=0;sub=frasm_f1.odd_top_data)&&(line_num<=frasm_f1.odd_bottom_data)) { + // Check for stray header inside the data. + if(current_line.isServiceLine()!=false) + { + // Make this line invalid. + current_line.clear(); + } + // Cycle through sub-lines in one line. for(uint8_t sub=0;sub0) + { + // Data if shifted upwards, no need for top padding. + frasm_f1.odd_top_padding = 0; + } + else + { + // Data if shifted downwards, convert preset offset to top padding, + // assuming top of the data not trimmed, but set by frame line number in [findFrameTrim()]. + frasm_f1.odd_top_padding = 0-preset_odd_offset; + } + // Calculate even field top padding. + if(preset_even_offset>0) + { + // Data if shifted upwards, no need for top padding. + frasm_f1.even_top_padding = 0; + } + else + { + // Data if shifted downwards, convert preset offset to top padding, + // assuming top of the data not trimmed, but set by frame line number in [findFrameTrim()]. + frasm_f1.even_top_padding = 0-preset_even_offset; + } + // Re-calculate bottom data trim to fit within standard number of lines per field. + frasm_f1.odd_bottom_padding = (frasm_f1.odd_bottom_data-frasm_f1.odd_top_data)/2+1; // Number of data lines. + frasm_f1.odd_bottom_padding += frasm_f1.odd_top_padding; // Data lines + top padding. + if(frasm_f1.odd_bottom_padding>LINES_PF) + { + frasm_f1.odd_bottom_padding -= LINES_PF; // Calculate how many excessive lines there are. + frasm_f1.odd_bottom_data -= (frasm_f1.odd_bottom_padding*2); // Trim bottom more (skipping every other line due to interlacing). + frasm_f1.odd_data_lines = (frasm_f1.odd_bottom_data-frasm_f1.odd_top_data)/2+1; // Re-calculate number of useful lines. + frasm_f1.odd_data_lines *= PCM1Line::SUBLINES_PER_LINE; // Convert number of lines to number of sublines. + } + // Re-calculate bottom data trim to fit within standard number of lines per field. + frasm_f1.even_bottom_padding = (frasm_f1.even_bottom_data-frasm_f1.even_top_data)/2+1; // Number of data lines. + frasm_f1.even_bottom_padding += frasm_f1.even_top_padding; // Data lines + top padding. + if(frasm_f1.even_bottom_padding>LINES_PF) + { + frasm_f1.even_bottom_padding -= LINES_PF; // Calculate how many excessive lines there are. + frasm_f1.even_bottom_data -= (frasm_f1.even_bottom_padding*2); // Trim bottom more (skipping every other line due to interlacing). + frasm_f1.even_data_lines = (frasm_f1.even_bottom_data-frasm_f1.even_top_data)/2+1; // Re-calculate number of useful lines. + frasm_f1.even_data_lines *= PCM1Line::SUBLINES_PER_LINE; // Convert number of lines to number of sublines. + } + // Calculate bottom padding to NTSC standard. + frasm_f1.odd_bottom_padding = (SUBLINES_PF-frasm_f1.odd_data_lines)/PCM1Line::SUBLINES_PER_LINE-frasm_f1.odd_top_padding; + frasm_f1.even_bottom_padding = (SUBLINES_PF-frasm_f1.even_data_lines)/PCM1Line::SUBLINES_PER_LINE-frasm_f1.even_top_padding; } + + //qDebug()<<"po"< *field_buf } else { - qWarning()<size()<<", start index:"<size()<<", start index:"<sample_rate); // Output L+R samples. - sample_pair.setSample(PCMSamplePair::CH_LEFT, in_block->getSample(wrd), in_block->isBlockValid(), in_block->isWordValid(wrd)); - sample_pair.setSample(PCMSamplePair::CH_RIGHT, in_block->getSample(wrd+1), in_block->isBlockValid(), in_block->isWordValid(wrd+1)); + sample_pair.setSample(PCMSamplePair::CH_LEFT, in_block->getSample(wrd), in_block->isBlockValid(), in_block->isWordValid(wrd), false); + sample_pair.setSample(PCMSamplePair::CH_RIGHT, in_block->getSample(wrd+1), in_block->isBlockValid(), in_block->isWordValid(wrd+1), false); // Put sample pair in the output queue. out_samples->push_back(sample_pair); mtx_samples->unlock(); @@ -1239,7 +1334,7 @@ void PCM1DataStitcher::outputFileStop() size_t queue_size; if((out_samples==NULL)||(mtx_samples==NULL)) { - qWarning()< conv_queue; // Output PCM lines buffer after trimming and padding, before converting into data blocks. std::string file_name; // Name of the file being processed (passed onto audio processing chain). uint8_t preset_field_order; // Field order, set externally. + int8_t preset_odd_offset; // Odd line offset, set externally. + int8_t preset_even_offset; // Even line offset, set externally. uint16_t log_level; // Level of debug output. uint16_t trim_fill; // Number of filled sub-lines in [trim_buf] from input queue. uint16_t f1_max_line; // Largest line number in Frame. bool ignore_CRC; // Ignore CRC from video lines or not (and force parity check). bool header_present; // Topmost line with header is detected in current frame. bool emphasis_set; // Current frame contains emphasis line flag. + bool auto_offset; // Auto line offset, set externally. bool file_start; // Detected start of a new file, filename saved to [file_name]. bool file_end; // Detected end of a file. bool finish_work; // Flag to break executing loop. @@ -116,6 +119,9 @@ class PCM1DataStitcher : public QObject public slots: void setLogLevel(uint16_t); // Set logging level. void setFieldOrder(uint8_t); // Preset field order. + void setAutoLineOffset(bool); // Preset auto line offset. + void setOddLineOffset(int8_t); // Preset odd line offset from the top. + void setEvenLineOffset(int8_t); // Preset even line offset from the top. void setFineUseECC(bool); // Set fine settings: usage of ECC on CRC-marked words. void setDefaultFineSettings(); // Set fine settings to defaults. void requestCurrentFineSettings(); // Get current fine settings. diff --git a/pcm1deinterleaver.cpp b/pcm1deinterleaver.cpp index 7ea4b31..3bfbc67 100644 --- a/pcm1deinterleaver.cpp +++ b/pcm1deinterleaver.cpp @@ -76,7 +76,7 @@ uint8_t PCM1Deinterleaver::processBlock(uint16_t itl_block_num, uint16_t line_sh if(out_data_block==NULL) { #ifdef DI_EN_DBG_OUT - qWarning()<clear(); @@ -189,7 +202,6 @@ PCMSamplePair::PCMSamplePair(const PCMSamplePair &in_object) samples[idx] = in_object.samples[idx]; } sample_rate = in_object.sample_rate; - index = in_object.index; emphasis = in_object.emphasis; service_type = in_object.service_type; file_path = in_object.file_path; @@ -204,7 +216,6 @@ PCMSamplePair& PCMSamplePair::operator= (const PCMSamplePair &in_object) samples[idx] = in_object.samples[idx]; } sample_rate = in_object.sample_rate; - index = in_object.index; emphasis = in_object.emphasis; service_type = in_object.service_type; file_path = in_object.file_path; @@ -220,7 +231,6 @@ void PCMSamplePair::clear() samples[idx].clear(); } sample_rate = SAMPLE_RATE_44056; - index = 0; emphasis = false; service_type = SRV_NO; file_path.clear(); @@ -245,7 +255,7 @@ void PCMSamplePair::setServEndFile() } //------------------------ Set sample for one channel. -bool PCMSamplePair::setSample(uint8_t channel, int16_t sample, bool block_ok, bool word_ok) +bool PCMSamplePair::setSample(uint8_t channel, int16_t sample, bool block_ok, bool word_ok, bool word_fixed) { if(channel>=CH_MAX) { @@ -253,15 +263,19 @@ bool PCMSamplePair::setSample(uint8_t channel, int16_t sample, bool block_ok, bo } samples[channel].audio_word = sample; samples[channel].data_block_ok = block_ok; - samples[channel].word_ok = word_ok; + samples[channel].word_valid = word_ok; + samples[channel].word_fixed = word_fixed; return true; } //------------------------ Set sample pair. -void PCMSamplePair::setSamplePair(int16_t ch1_sample, int16_t ch2_sample, bool ch1_block, bool ch2_block, bool ch1_word, bool ch2_word) +void PCMSamplePair::setSamplePair(int16_t ch1_sample, int16_t ch2_sample, + bool ch1_block, bool ch2_block, + bool ch1_word, bool ch2_word, + bool ch1_fixed, bool ch2_fixed) { - setSample(CH_LEFT, ch1_sample, ch1_block, ch1_word); - setSample(CH_RIGHT, ch2_sample, ch2_block, ch2_word); + setSample(CH_LEFT, ch1_sample, ch1_block, ch1_word, ch1_fixed); + setSample(CH_RIGHT, ch2_sample, ch2_block, ch2_word, ch2_fixed); } //------------------------ Set (irreversably) samples validity by data block validity. @@ -285,10 +299,10 @@ void PCMSamplePair::setSampleRate(uint16_t in_rate) //------------------------ Set index of the set. void PCMSamplePair::setIndex(uint64_t in_idx) { - index = in_idx; + // Set the same index for all underlying samples. for(uint8_t idx=0;idx #include +#include #include "config.h" //------------------------ Single 16-bit audio sample container. @@ -22,11 +23,12 @@ class PCMSample }; public: - int16_t audio_word; - uint64_t index; - bool data_block_ok; - bool word_ok; - bool word_processed; + int16_t audio_word; // Audio data (16-bit) zero-centered. + uint64_t index; // Global sample index from the start of the source. + bool data_block_ok; // Was source data block valid? + bool word_valid; // Does this sample contain valid audio data? + bool word_fixed; // Was this sample fixed with error correction while deinterleaving? + bool word_masked; // Was this sample altered in audio processor? (mute, interpolation) public: PCMSample(); @@ -36,15 +38,17 @@ class PCMSample void setValue(int16_t in_val); void setIndex(uint64_t in_idx); void setInvalid(); + void setValid(); void setFixed(); - void setProcessed(); + void setMasked(); void setValidityByBlock(); int16_t getValue(); uint16_t getAmplitude(); uint64_t getIndex(); bool isSilent(); bool isValid(); - bool isProcessed(); + bool isFixed(); + bool isMasked(); std::string dumpWordsString(); }; @@ -73,16 +77,15 @@ class PCMSamplePair // Service tags for [service_type]. enum { - SRV_NO, // Regular PCM line with audio data. - SRV_NEW_FILE, // New file opened (with path in [file_path]). - SRV_END_FILE, // File ended. + SRV_NO, // Regular PCM line with audio data. + SRV_NEW_FILE, // New file opened (with path in [file_path]). + SRV_END_FILE, // File ended. }; public: - PCMSample samples[CH_MAX]; - uint16_t sample_rate; - uint64_t index; - bool emphasis; + PCMSample samples[CH_MAX]; // Sample set for this data point. + uint16_t sample_rate; // Sample rate for this data point. + bool emphasis; // Do samples need de-emphasis? uint8_t service_type; // Type of the service tag. std::string file_path; // Path of decoded file (set with [SRV_NEW_FILE]). @@ -93,8 +96,11 @@ class PCMSamplePair void clear(); void setServNewFile(std::string path); void setServEndFile(); - bool setSample(uint8_t channel, int16_t sample, bool block_ok, bool word_ok); - void setSamplePair(int16_t ch1_sample, int16_t ch2_sample, bool ch1_block, bool ch2_block, bool ch1_word, bool ch2_word); + bool setSample(uint8_t channel, int16_t sample, bool block_ok = true, bool word_ok = true, bool word_fixed = false); + void setSamplePair(int16_t ch1_sample, int16_t ch2_sample, + bool ch1_block, bool ch2_block, + bool ch1_word = true, bool ch2_word = true, + bool ch1_fixed = false, bool ch2_fixed = false); void setValidityByBlock(); void setSampleRate(uint16_t in_rate); void setIndex(uint64_t in_idx); diff --git a/renderpcm.cpp b/renderpcm.cpp index aa1dbc3..b899b57 100644 --- a/renderpcm.cpp +++ b/renderpcm.cpp @@ -5,6 +5,7 @@ RenderPCM::RenderPCM(QObject *parent) Q_UNUSED(parent); live_pb = true; + drawer_ready = true; frame_time_lim = TIME_NTSC; frame_number = 0; fill_line_num = 0; @@ -14,9 +15,7 @@ RenderPCM::RenderPCM(QObject *parent) img_data = new QImage(640, 480, QImage::Format_RGB32); img_data->fill(Qt::black); - pix_data = QPixmap::fromImage(*img_data); - - qInfo()<<"[REN] Launched, thread:"<thread()<<"ID"<thread()<<"ID"<width()!=provided_width)||(img_data->height()!=provided_heigth)) { - pix_data.fill(Qt::black); // Resize container if required. if(img_data!=NULL) { @@ -179,26 +178,21 @@ void RenderPCM::finishNewFrame(uint32_t in_frame_no) #ifdef VIS_EN_DBG_OUT qInfo()<<"[REN] Frame"<copy(), frame_number); + // Clear ready flag. + drawer_ready = false; } - // Restart frame timer. - frame_time.start(); } //------------------------ Insert next video line into the frame. @@ -471,7 +465,7 @@ void RenderPCM::renderNewLine(PCM1Line in_line) (line_bit>(PCM1Line::BITS_PCM_DATA-in_line.picked_bits_right-1))) { // Highlight picked bits. - *pixel_ptr = VIS_BIT0_GRN; + *pixel_ptr = VIS_BIT0_BLU; } } else if(in_line.isForcedBad()!=false) @@ -501,7 +495,7 @@ void RenderPCM::renderNewLine(PCM1Line in_line) (line_bit>(PCM1Line::BITS_PCM_DATA-in_line.picked_bits_right-1))) { // Highlight picked bits. - *pixel_ptr = VIS_BIT1_GRN; + *pixel_ptr = VIS_BIT1_BLU; } } else if(in_line.isForcedBad()!=false) @@ -594,7 +588,7 @@ void RenderPCM::renderNewLine(PCM1SubLine in_line) if((line_bit(PCM16X0SubLine::BITS_PCM_DATA-in_line.picked_bits_right-1))) { // Highlight picked bits. - *pixel_ptr = VIS_BIT0_GRN; + *pixel_ptr = VIS_BIT0_BLU; } } else if(in_line.isForcedBad()!=false) @@ -757,7 +751,7 @@ void RenderPCM::renderNewLine(PCM16X0SubLine in_line) if((line_bit(PCM16X0SubLine::BITS_PCM_DATA-in_line.picked_bits_right-1))) { - *pixel_ptr = VIS_BIT1_GRN; + *pixel_ptr = VIS_BIT1_BLU; } } else if(in_line.isForcedBad()!=false) @@ -922,20 +916,20 @@ void RenderPCM::renderNewLine(STC007Line in_line) if((in_line.getWord(word)&(1< #include #include -#include #include #include "frametrimset.h" #include "pcm1datablock.h" @@ -27,10 +26,10 @@ #define VIS_BIT0_BLK (Qt::black) // Bit "0", PCM with valid CRC in the line. #define VIS_BIT0_GRY (qRgb(45, 45, 45)) // Bit "0", PCM with valid CRC in the line for STC-007. #define VIS_BIT1_GRY (qRgb(150, 150, 150)) // Bit "1", PCM with valid CRC in the line. -#define VIS_BIT0_YEL (qRgb(127, 116, 0)) // Bit "0", PCM with yellow tint. -#define VIS_BIT1_YEL (qRgb(255, 233, 0)) // Bit "1", PCM with yellow tint. -#define VIS_BIT0_GRN (qRgb(0, 90, 0)) // Bit "0", PCM with green tint. -#define VIS_BIT1_GRN (qRgb(0, 220, 0)) // Bit "1", PCM with green tint. +#define VIS_BIT0_YEL (qRgb(127, 110, 0)) // Bit "0", PCM with yellow tint. +#define VIS_BIT1_YEL (qRgb(255, 220, 0)) // Bit "1", PCM with yellow tint. +#define VIS_BIT0_GRN (qRgb(0, 95, 30)) // Bit "0", PCM with green tint. +#define VIS_BIT1_GRN (qRgb(0, 225, 70)) // Bit "1", PCM with green tint. #define VIS_BIT0_RED (qRgb(140, 0, 0)) // Bit "0", PCM with red tint. #define VIS_BIT1_RED (qRgb(255, 70, 43)) // Bit "1", PCM with red tint. #define VIS_BIT0_BLU (qRgb(0, 95, 127)) // Bit "0", PCM with blue tint. @@ -80,10 +79,10 @@ class RenderPCM : public QObject void resetFrame(); private: - QPixmap pix_data; QImage *img_data; QElapsedTimer frame_time; bool live_pb; + bool drawer_ready; uint8_t frame_time_lim; uint32_t frame_number; uint16_t fill_line_num; @@ -117,9 +116,10 @@ public slots: void renderNewBlock(PCM1DataBlock); void renderNewBlock(PCM16X0DataBlock); void renderNewBlock(STC007DataBlock); + void displayIsReady(); signals: - void newFrame(QPixmap, uint32_t); + void newFrame(QImage, uint32_t); }; #endif // RENDERPCM_H diff --git a/samples2wav.cpp b/samples2wav.cpp index 8695c3d..b3c14d3 100644 --- a/samples2wav.cpp +++ b/samples2wav.cpp @@ -23,9 +23,188 @@ const uint8_t SamplesToWAV::default_header[SamplesToWAV::HDR_SZ] = SamplesToWAV::SamplesToWAV() { log_level = 0; + error_lock = false; sample_rate = PCMSamplePair::SAMPLE_RATE_44056; } +//------------------------ Open output file. +bool SamplesToWAV::openOutput() +{ + if(error_lock!=false) + { + return false; + } + // Check if file is not yet opened. + if(file_out.isOpen()!=false) + { + return true; + } + if((file_path.isNull()!=false)||(file_name.isNull()!=false)|| + (file_path.isEmpty()!=false)||(file_name.isEmpty()!=false)) + { + return false; + } +#ifdef TW_EN_DBG_OUT + if((log_level&LOG_PROCESS)!=0) + { + qInfo()<<"[TW] File is not opened yet, creating/rewriting new..."; + } +#endif + output_path = file_path+"/"+file_name+"_v"+APP_VERSION+".wav"; + // Open file to append. + file_out.setFileName(output_path); + file_out.open(QIODevice::ReadWrite|QIODevice::Truncate); + // Check if file opened. + if(file_out.isOpen()!=false) + { + // File opened ok. + // Write default WAV header. + addHeader(); + return true; + } + // No luck, failed to open. + error_lock = true; +#ifdef QT_VERSION + qWarning()<0)) + if(audio_state==AUD_BROKEN) { - // 14-bit data block has some errors marked with CRC, but all error-correction words are bad, - // so data block was not fixed or checked for possible BROKEN state, thus to prevent future use of not-damaged words in the block - // due to its probable misassembling, invalidate all words. - full_bad = true; + return; } - else if((resolution==RES_16BIT)&&(line_crc[WORD_P0]==false)&&(getErrorsAudioSource()>0)) + uint8_t ind_limit; + // Determine word limit. + if(resolution==RES_16BIT) { - // 16-bit data block has some errors marked with CRC, but error-correction word is bad, - // so data block was not fixed or checked for possible BROKEN state, thus to prevent future use of not-damaged words in the block - // due to its probable misassembling, invalidate all words. - full_bad = true; + // Up to P word for 16-bit mode. + ind_limit = WORD_P0; } - if(audio_state!=AUD_BROKEN) + else { - uint8_t ind_limit; - // Determine word limit. - if(resolution==RES_16BIT) - { - // Up to P word for 16-bit mode. - ind_limit = WORD_P0; - } - else - { - // Up to Q word for 14-bit mode. - ind_limit = WORD_Q0; - } - // Revert word validity to "before error-correction" state, - // so damaged words that could be incorrectly "fixed" due to misassembling will be interpolated later. - for(uint8_t index=WORD_L0;index<=ind_limit;index++) - { - if(full_bad==false) - { - // Revert word validity to "before error-correction" state. - word_valid[index] = line_crc[index]; - } - else - { - // Shut down the whole data block. - word_valid[index] = false; - } - line_crc[index] = cwd_fixed[index] = false; - } - audio_state = AUD_ORIG; - cwd_applied = false; + // Up to Q word for 14-bit mode. + ind_limit = WORD_Q0; + } + // Revert words validity to "before error-correction" state, + // so damaged words that could be incorrectly "fixed" due to misassembling will be interpolated later. + for(uint8_t index=WORD_L0;index<=ind_limit;index++) + { + // Revert word validity to "before error-correction" state. + word_valid[index] = line_crc[index]; + line_crc[index] = cwd_fixed[index] = false; + } + audio_state = AUD_ORIG; + cwd_applied = false; #ifdef DB_EN_DBG_OUT - QString log_line; - log_line.sprintf("[DB] Marked INVALID [%03u/%03u...%03u/%03u]", start_frame, start_line, stop_frame, stop_line); - qInfo()<0) { - valid = false; + return false; } - return valid; + return true; } -//------------------------ Check if data block was repaired by Cross-Word Decoding. -bool STC007DataBlock::isDataFixedByCWD() +//------------------------ Check if some audio words in data block were repaired using Cross-Word Decoding. +bool STC007DataBlock::isAudioAlteredByCWD() { - bool cwd_det; - - cwd_det = false; + for(uint8_t index=WORD_L0;index<=WORD_R2;index++) + { + if(isWordCWDFixed(index)!=false) + { + return true; + } + } + return false; +} - if(cwd_applied!=false) +//------------------------ Check if some words in data block were repaired using Cross-Word Decoding. +bool STC007DataBlock::isDataAlteredByCWD() +{ + for(uint8_t index=WORD_L0;index<=WORD_Q0;index++) { - for(uint8_t index=WORD_L0;index<=WORD_Q0;index++) + if(isWordCWDFixed(index)!=false) { - if(isWordCWDFixed(index)!=false) - { - cwd_det = true; - } + return true; } } - return cwd_det; + return false; +} + +//------------------------ Check if data block was repaired using Cross-Word Decoding. +bool STC007DataBlock::isDataFixedByCWD() +{ + if(cwd_applied!=false) + { + return isDataAlteredByCWD(); + } + return false; } //------------------------ Check if data block was repaired by P-code. @@ -364,10 +347,7 @@ bool STC007DataBlock::isDataFixedByP() { return true; } - else - { - return false; - } + return false; } //------------------------ Check if data block was repaired by Q-code. @@ -377,23 +357,23 @@ bool STC007DataBlock::isDataFixedByQ() { return true; } - else - { - return false; - } + return false; } //------------------------ Check if data block was repaired. bool STC007DataBlock::isDataFixed() { - if((isDataFixedByP()==false)&&(isDataFixedByQ()==false)) - { - return false; - } - else + for(uint8_t index=WORD_L0;index<=WORD_Q0;index++) { - return true; + if(line_crc[index]==false) + { + if(word_valid[index]!=false) + { + return true; + } + } } + return false; } //------------------------ Check if data block is broken (probably frame miss or bad frame stitching). @@ -403,10 +383,7 @@ bool STC007DataBlock::isDataBroken() { return true; } - else - { - return false; - } + return false; } //------------------------ Check if data block contains 14-bit audio samples. @@ -416,10 +393,7 @@ bool STC007DataBlock::isData14bit() { return true; } - else - { - return false; - } + return false; } //------------------------ Check if data block contains 16-bit audio samples. @@ -429,10 +403,7 @@ bool STC007DataBlock::isData16bit() { return true; } - else - { - return false; - } + return false; } //------------------------ Is audio sample near zero value? @@ -451,7 +422,6 @@ bool STC007DataBlock::isNearSilence(uint8_t index) { return false; } - return true; } else { @@ -464,8 +434,8 @@ bool STC007DataBlock::isNearSilence(uint8_t index) { return false; } - return true; } + return true; } //------------------------ Are most audio samples are near "0"? @@ -507,10 +477,7 @@ bool STC007DataBlock::isOnSeam() { return true; } - else - { - return false; - } + return false; } //------------------------ Do samples in the block need de-emphasis for playback? @@ -526,10 +493,7 @@ uint16_t STC007DataBlock::getWord(uint8_t index) { return words[index]; } - else - { - return 0; - } + return 0; } //------------------------ Get audio sample according to its resolution. @@ -548,10 +512,7 @@ int16_t STC007DataBlock::getSample(uint8_t index) return (int16_t)(words[index]<<2); } } - else - { - return 0; - } + return 0; } //------------------------ Get resolution of audio samples. @@ -582,6 +543,22 @@ uint8_t STC007DataBlock::getErrorsAudioSource() return crc_errs; } +//------------------------ Get error count for audio samples (after CWD, before ECC). +uint8_t STC007DataBlock::getErrorsAudioCWD() +{ + uint8_t crc_errs; + crc_errs = 0; + // Search for audio samples with bad CRC. + for(uint8_t index=WORD_L0;index<=WORD_R2;index++) + { + if((line_crc[index]==false)&&(cwd_fixed[index]==false)) + { + crc_errs++; + } + } + return crc_errs; +} + //------------------------ Get error count for audio samples (after corrections). uint8_t STC007DataBlock::getErrorsAudioFixed() { @@ -626,6 +603,34 @@ uint8_t STC007DataBlock::getErrorsTotalSource() return crc_errs; } +//------------------------ Get total error count for all words (after CWD, before ECC). +uint8_t STC007DataBlock::getErrorsTotalCWD() +{ + uint8_t crc_errs; + crc_errs = 0; + + // Determine word limit. + uint8_t ind_limit; + if(resolution==RES_16BIT) + { + ind_limit = WORD_P0; + } + else + { + ind_limit = WORD_Q0; + } + + // Search for words with bad CRC. + for(uint8_t index=WORD_L0;index<=ind_limit;index++) + { + if((line_crc[index]==false)&&(cwd_fixed[index]==false)) + { + crc_errs++; + } + } + return crc_errs; +} + //------------------------ Get total error count for all words (before correction). uint8_t STC007DataBlock::getErrorsTotalFixed() { @@ -846,8 +851,10 @@ std::string STC007DataBlock::dumpContentString() } text_out += "] "; - sprintf(c_buf, "EA[%01u|%01u] ET[%01u|%01u] T[%04u] ", - getErrorsAudioSource(), getErrorsAudioFixed(), getErrorsTotalSource(), getErrorsTotalFixed(), process_time); + sprintf(c_buf, "EA[%01u|%01u|%01u] ET[%01u|%01u|%01u] T[%04u] ", + getErrorsAudioSource(), getErrorsAudioCWD(), getErrorsAudioFixed(), + getErrorsTotalSource(), getErrorsTotalCWD(), getErrorsTotalFixed(), + process_time); text_out += c_buf; if(isSilent()!=false) @@ -886,13 +893,17 @@ std::string STC007DataBlock::dumpContentString() if(audio_state==AUD_ORIG) { - if(isDataFixedByCWD()==false) + if(isDataFixedByCWD()!=false) { - sprintf(c_buf, "ORIG "); + sprintf(c_buf, "O_CWD"); + } + else if(isDataFixed()!=false) + { + sprintf(c_buf, "FIXED"); } else { - sprintf(c_buf, "O_CWD"); + sprintf(c_buf, "ORIG "); } } else if(audio_state==AUD_FIX_P) diff --git a/stc007datablock.h b/stc007datablock.h index 3a53f03..79eb452 100644 --- a/stc007datablock.h +++ b/stc007datablock.h @@ -109,7 +109,7 @@ class STC007DataBlock uint16_t w_line[WORD_CNT]; // Number of source lines for words. uint16_t sample_rate; // Sample rate of samples in the data block [Hz]. bool emphasis; // Do samples need de-emphasis for playback? - bool cwd_applied; // Flag for CWD correction applied. + bool cwd_applied; // Flag for fixing block with CWD (applied corrections from ECC pre-scan). uint32_t process_time; // Amount of time spent processing the data block [us]. private: @@ -145,6 +145,8 @@ class STC007DataBlock bool isWordCWDFixed(uint8_t index); bool isWordValid(uint8_t index); bool isBlockValid(); + bool isAudioAlteredByCWD(); + bool isDataAlteredByCWD(); bool isDataFixedByCWD(); bool isDataFixedByP(); bool isDataFixedByQ(); @@ -162,8 +164,10 @@ class STC007DataBlock uint8_t getResolution(); uint8_t getAudioState(); uint8_t getErrorsAudioSource(); + uint8_t getErrorsAudioCWD(); uint8_t getErrorsAudioFixed(); uint8_t getErrorsTotalSource(); + uint8_t getErrorsTotalCWD(); uint8_t getErrorsTotalFixed(); uint32_t getStartFrame(); uint32_t getStopFrame(); diff --git a/stc007datastitcher.cpp b/stc007datastitcher.cpp index ff936c2..5499c3c 100644 --- a/stc007datastitcher.cpp +++ b/stc007datastitcher.cpp @@ -42,7 +42,7 @@ void STC007DataStitcher::setInputPointers(std::deque *in_pcmline, QM { if((in_pcmline==NULL)||(mtx_pcmline==NULL)) { - qWarning()< *out_pcmsam { if((out_pcmsamples==NULL)||(mtx_pcmsamples==NULL)) { - qWarning()< *field, u } // Check if provided size exceeds data size in the container. - if(field->size()<=f_size) + if(field->size()size()< *field, u } else { - //qWarning()< *in_li if(in_line_buffer->size()<=(size_t)(line_sh+STC007DataBlock::MIN_DEINT_DATA)) { - qWarning()<size()<<(line_sh+STC007DataBlock::MIN_DEINT_DATA); return STC007Deinterleaver::RES_MODE_14BIT_AUTO; } @@ -1439,6 +1473,7 @@ uint8_t STC007DataStitcher::tryPadding(std::vector *field1, uint16_t { bool suppress_log, run_lock; uint8_t ext_di_log_lvl; + uint8_t unchecked_lim; uint16_t line_count, line_num; uint16_t valid_burst_count, silence_burst_count, uncheck_burst_count, broken_count; uint16_t valid_burst_max, silence_burst_max, uncheck_burst_max, brk_burst_max; @@ -1457,13 +1492,13 @@ uint8_t STC007DataStitcher::tryPadding(std::vector *field1, uint16_t #endif if((field1==NULL)||(field2==NULL)) { - qWarning()<size()<=f1_size)||(field2->size()<=f2_size)) + if((field1->size()size()size()<size()< *field1, uint16_t valid_burst_count = silence_burst_count = uncheck_burst_count = broken_count = 0; valid_burst_max = silence_burst_max = uncheck_burst_max = brk_burst_max = 0; + unchecked_lim = max_unchecked_14b_blocks; + if(enable_Q_code==false) + { + unchecked_lim = max_unchecked_16b_blocks; + } + // Set parameters for test conversion. ext_di_log_lvl = 0; if(((log_level&LOG_PADDING)!=0)&&((log_level&LOG_DEINTERLEAVE)!=0)) @@ -1636,23 +1677,7 @@ uint8_t STC007DataStitcher::tryPadding(std::vector *field1, uint16_t // Block can not be checked for validity. uncheck_burst_count++; // Choose limit according to resolution. - /*if(padding_block.isData16bit()==false) - { - // 14-bit data. - if(uncheck_burst_count>=max_unchecked_14b_blocks) - { - valid_burst_count = 0; - } - } - else - { - // 16-bit data. - if(uncheck_burst_count>=max_unchecked_16b_blocks) - { - valid_burst_count = 0; - } - }*/ - if(uncheck_burst_count>=0x38) + if(uncheck_burst_count>=unchecked_lim) { valid_burst_count = 0; } @@ -1744,7 +1769,7 @@ uint8_t STC007DataStitcher::tryPadding(std::vector *field1, uint16_t // Too much silence. return DS_RET_SILENCE; } - if(uncheck_burst_max>0x38) + if(uncheck_burst_max>unchecked_lim) { // Too many unchecked. return DS_RET_NO_PAD; @@ -1766,27 +1791,43 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ { bool suppress_log; uint16_t pad, max_padding, min_broken; - uint8_t stitch_res; + uint8_t unchecked_lim, no_brk_idx, stitch_res; stitch_res = DS_RET_NO_PAD; suppress_log = !(((log_level&LOG_PADDING)!=0)&&((log_level&LOG_PROCESS)!=0)); if((field1==NULL)||(field2==NULL)||(padding==NULL)) { - qWarning()<LINES_PF_PAL) + { + (*padding) = 0; + } + else + { + (*padding) = LINES_PF_PAL - pad; + } } else if(in_std==FrameAsmDescriptor::VID_NTSC) { - (*padding) = LINES_PF_NTSC - pad; + if(pad>LINES_PF_NTSC) + { + (*padding) = 0; + } + else + { + (*padding) = LINES_PF_NTSC - pad; + } } else { @@ -1800,11 +1841,13 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ #endif max_padding = MAX_PADDING_14BIT; + unchecked_lim = max_unchecked_14b_blocks; // Check Q-code availability to set maximum padding distance. if((in_resolution==STC007DataBlock::RES_16BIT)||(enable_Q_code==false)) { // Without Q-code maximum padding is half of that of PQ mode. max_padding = MAX_PADDING_16BIT; + unchecked_lim = max_unchecked_16b_blocks; } #ifdef DI_EN_DBG_OUT if(suppress_log==false) @@ -1820,39 +1863,35 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ // Initialize stats data. std::vector stitch_data; stitch_data.resize(max_padding); + min_broken = 0xFFFF; + no_brk_idx = 0; // Padding cycle, collect stats data. for(pad=0;padstitch_data[pad].broken) { - tmp.sprintf("%02u", stitch_data[pad].index); - index_line += "|"+tmp; - tmp.sprintf("%02x", stitch_data[pad].broken); - broken_line += "|"+tmp; - tmp.sprintf("%02x", stitch_data[pad].valid); - valid_line += "|"+tmp; - tmp.sprintf("%02x", stitch_data[pad].unchecked); - unchecked_line += "|"+tmp; - tmp.sprintf("%02x", stitch_data[pad].silent); - silence_line += "|"+tmp; + // Min minimum. + min_broken = stitch_data[pad].broken; + if(min_broken==0) + { + no_brk_idx = pad; + } } - qInfo()<<"[L2B-007] Padding sweep stats:"; - qInfo()<<"[L2B-007] Padding: "<0)&&(stitch_data[no_brk_idx].unchecked0)) + { + // Padding with no broken blocks passes checks for number of valid and unchecked blocks. + // Current one has more broken blocks, no need to check further. + break; + } + } + } // Search for minimum number of broken blocks. // Sort by number of valid blocks from max to min. @@ -1861,8 +1900,6 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ // If its unchecked blocks count is less than allowed - set as detected padding. std::sort(stitch_data.begin(), stitch_data.end()); - // Find minimum broken blocks within all passes. - min_broken = stitch_data[0].broken; #ifdef DI_EN_DBG_OUT if(suppress_log==false) { @@ -1895,10 +1932,10 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ if(stitch_data[0].silent *field1, uint16_ } #endif } - else if(((int16_t)stitch_data[0].valid-(int16_t)stitch_data[1].valid)>MAX_BURST_UNCH) + else if((((int16_t)stitch_data[0].valid-(int16_t)stitch_data[1].valid)>MAX_BURST_UNCH_DELTA)&&(stitch_data[0].broken==0)) { stitch_res = DS_RET_OK; (*padding) = stitch_data[0].index; @@ -1921,7 +1958,7 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ } #endif } - else if(((int16_t)stitch_data[1].unchecked-(int16_t)stitch_data[0].unchecked)>MAX_BURST_UNCH) + /*else if((((int16_t)stitch_data[1].unchecked-(int16_t)stitch_data[0].unchecked)>MAX_BURST_UNCH_DELTA)&&(stitch_data[0].broken==0)) { stitch_res = DS_RET_OK; (*padding) = stitch_data[0].index; @@ -1931,7 +1968,7 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ qInfo()<<"[L2B-007] Detected valid (but suspicious) padding of"< *field1, uint16_ for(pad=0;pad=0x38) + if(stitch_data[pad].unchecked>=unchecked_lim) { stitch_data[pad].broken = 0xFF; } @@ -1988,10 +2025,10 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ qInfo()<<"[L2B-007] Silent: "<MAX_BURST_UNCH) + if(((int16_t)stitch_data[0].valid-(int16_t)stitch_data[1].valid)>MAX_BURST_UNCH_DELTA) { stitch_res = DS_RET_OK; (*padding) = stitch_data[0].index; @@ -2002,7 +2039,7 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ } #endif } - else if(((int16_t)stitch_data[1].unchecked-(int16_t)stitch_data[0].unchecked)>MAX_BURST_UNCH) + /*else if(((int16_t)stitch_data[1].unchecked-(int16_t)stitch_data[0].unchecked)>MAX_BURST_UNCH_DELTA) { stitch_res = DS_RET_OK; (*padding) = stitch_data[0].index; @@ -2012,7 +2049,7 @@ uint8_t STC007DataStitcher::findPadding(std::vector *field1, uint16_ qInfo()<<"[L2B-007] Detected valid (but suspicious) padding of"<=DI_FIELD_MIN_LINES)) if((en_sw_order!=false)&&(frasm_f1.even_data_lines>=MIN_FILL_LINES_PF)) { #ifdef DI_EN_DBG_OUT @@ -3949,6 +4047,7 @@ uint8_t STC007DataStitcher::findFieldStitching() } } } +//------------------------ Processing A-B padding (BFF to TFF). else if(proc_state==STG_AB_BFF_TO_TFF) { #ifdef DI_EN_DBG_OUT @@ -3968,8 +4067,6 @@ uint8_t STC007DataStitcher::findFieldStitching() // Padding detected successfully. frasm_f1.outer_padding_ok = true; frasm_f2.setOrderTFF(); - // Save video mode. - //updateVideoStandard(guess_vid); // Work is done. proc_state = STG_PAD_OK; if(frasm_f1.isOrderSet()==false) @@ -4004,7 +4101,6 @@ uint8_t STC007DataStitcher::findFieldStitching() frasm_f1.outer_silence = true; frasm_f1.outer_padding = 0; frasm_f1.outer_padding_ok = false; - //frasm_f2.setOrderUnknown(); frasm_f2.inner_padding_ok = false; #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) @@ -4019,10 +4115,8 @@ uint8_t STC007DataStitcher::findFieldStitching() // Did not find padding between frames. frasm_f1.outer_padding = 0; frasm_f1.outer_padding_ok = false; - //frasm_f2.setOrderUnknown(); frasm_f2.inner_padding_ok = false; // Check if Frame A is preset to be BFF. - //if((frasm_f1.isOrderBFF()==false)&&(f1e_index>=DI_FIELD_MIN_LINES)) if((en_sw_order!=false)&&(frasm_f1.even_data_lines>=MIN_FILL_LINES_PF)) { #ifdef DI_EN_DBG_OUT @@ -4043,6 +4137,7 @@ uint8_t STC007DataStitcher::findFieldStitching() } } //------------------------ General states. +//------------------------ Padding is done successfully. else if(proc_state==STG_PAD_OK) { // Field order and paddings are found successfully. @@ -4052,10 +4147,10 @@ uint8_t STC007DataStitcher::findFieldStitching() qInfo()<<"[L2B-007] Frame padding detected successfully."; } #endif - //qDebug()<<"[DI] Stage"<STG_PAD_MAX) { #ifdef DI_EN_DBG_OUT - qWarning()< *field_bu } else { - qWarning()<size()<<", start index:"<size()<<", start index:"<target_lines_per_field) + { + qWarning()<target_lines_per_field) { - // Ignore video standard line count, assemble fields as is. - target_lines_per_field = 0; + qWarning()<lines_to_fill) + { +#ifdef DI_EN_DBG_OUT + if(suppress_anylog==false) + { + qInfo()<<"[L2B-007] Data anchors: ABC, path: not enough lines"; + } +#endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (full field). + added_lines_cnt += addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); // Add field-to-field padding. added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); added_lines_cnt += added_inner; @@ -4663,21 +4791,33 @@ void STC007DataStitcher::fillFrameForOutput() added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); // Add frame-to-frame padding. added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); + // Add padding up to frame standard. + added_outer += addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); added_lines_cnt += added_outer; + // Need to invalidate bottom seam. + frasm_f1.outer_padding_ok = false; + frasm_f2.setOrderUnknown(); +#ifdef DI_EN_DBG_OUT + if(suppress_anylog==false) + { + qInfo()<<"[L2B-007] Frames A-B ("<=lines_to_fill) { #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: ABC, path: frame size is correct"; + qInfo()<<"[L2B-007] Data anchors: ABC, path: too many lines, cutting padding"; } #endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). @@ -4689,20 +4829,20 @@ void STC007DataStitcher::fillFrameForOutput() last_line = getSecondFieldLineNum(cur_field_order); // Add lines from second field (full field). added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); + // Add padding up to frame standard. + added_outer = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); added_lines_cnt += added_outer; } - else if((target_lines_per_field*2)>lines_to_fill) + else { #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: ABC, path: not enough lines"; + qInfo()<<"[L2B-007] Data anchors: ABC, path: too many lines, cutting second field"; } #endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). @@ -4712,84 +4852,18 @@ void STC007DataStitcher::fillFrameForOutput() added_lines_cnt += added_inner; // Reset line number. last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - // Add padding up to frame standard. - added_outer += addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - added_lines_cnt += added_outer; - // Need to invalidate bottom seam. - frasm_f1.outer_padding_ok = false; - frasm_f2.setOrderUnknown(); -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Frames A-B ("<=lines_to_fill) - { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: ABC, path: too many lines, cutting padding"; - } -#endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt += addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add padding up to frame standard. - added_outer = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - added_lines_cnt += added_outer; - } - else - { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: ABC, path: too many lines, cutting second field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt += addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (cut data from the end). - added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); - } - // Need to invalidate bottom seam. - frasm_f1.outer_padding_ok = false; - frasm_f2.setOrderUnknown(); + // Need to invalidate bottom seam. + frasm_f1.outer_padding_ok = false; + frasm_f2.setOrderUnknown(); #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Frames A-B ("<=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: AB, path: no limits"; + qInfo()<<"[L2B-007] Data anchors: AB, path: adding padding"; } #endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). @@ -4817,59 +4895,31 @@ void STC007DataStitcher::fillFrameForOutput() last_line = getSecondFieldLineNum(cur_field_order); // Add lines from second field (full field). added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); + // Add padding up to frame standard. + added_outer = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); + added_lines_cnt += added_outer; } else { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.inner_padding; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) - { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: AB, path: adding padding"; - } -#endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add padding up to frame standard. - added_outer = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_anylog==false) { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: AB, path: too many lines, cutting second field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (cut data from the end). - added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); + qInfo()<<"[L2B-007] Data anchors: AB, path: too many lines, cutting second field"; } +#endif + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (full field). + added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Add field-to-field padding. + added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); + added_lines_cnt += added_inner; + // Reset line number. + last_line = getSecondFieldLineNum(cur_field_order); + // Add lines from second field (cut data from the end). + added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); } } } @@ -4878,19 +4928,26 @@ void STC007DataStitcher::fillFrameForOutput() // Anchor A and anchor C present. // No anchor B. // AC - if(target_lines_per_field==0) + // Calculate total number of lines for frame assembly. + lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.outer_padding; + // Check line count according to video standard. + if((target_lines_per_field*2)>=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: AC, path: no limits"; + qInfo()<<"[L2B-007] Data anchors: AC, path: adding padding"; } #endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Add padding up to frame standard. + added_inner = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); + added_lines_cnt += added_inner; // Reset line number. last_line = getSecondFieldLineNum(cur_field_order); // Add lines from second field (full field). @@ -4901,56 +4958,25 @@ void STC007DataStitcher::fillFrameForOutput() } else { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.outer_padding; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) - { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: AC, path: adding padding"; - } -#endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add padding up to frame standard. - added_inner = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_anylog==false) { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: AC, path: too many lines, cutting second field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (cut data from the start). - added_lines_cnt += addLinesFromField(p_field_2, lines_to_fill, (field_2_cnt-lines_to_fill), &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - added_lines_cnt += added_outer; + qInfo()<<"[L2B-007] Data anchors: AC, path: too many lines, cutting second field"; } +#endif + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (full field). + added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Reset line number. + last_line = getSecondFieldLineNum(cur_field_order); + // Add lines from second field (cut data from the start). + added_lines_cnt += addLinesFromField(p_field_2, lines_to_fill, (field_2_cnt-lines_to_fill), &last_line); + // Add frame-to-frame padding. + added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); + added_lines_cnt += added_outer; } } else @@ -4958,71 +4984,50 @@ void STC007DataStitcher::fillFrameForOutput() // Anchor A present. // No anchor B and anchor C. // A - if(target_lines_per_field==0) + // Calculate total number of lines for frame assembly. + lines_to_fill = field_1_cnt+field_2_cnt; + // Check line count according to video standard. + if((target_lines_per_field*2)>=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: A, path: no limits"; + qInfo()<<"[L2B-007] Data anchors: A, path: adding padding"; } #endif // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Add padding up to field standard. + added_inner = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_1_cnt), &last_line); + added_lines_cnt += added_inner; // Reset line number. last_line = getSecondFieldLineNum(cur_field_order); // Add lines from second field (full field). added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); + // Add padding up to field standard. + added_outer = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_2_cnt), &last_line); + added_lines_cnt += added_outer; } else { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) - { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: A, path: adding padding"; - } -#endif - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add padding up to field standard. - added_inner = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_1_cnt), &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add padding up to field standard. - added_outer = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_2_cnt), &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_anylog==false) { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: A, path: too many lines, cutting second field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (cut data from the end). - added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); + qInfo()<<"[L2B-007] Data anchors: A, path: too many lines, cutting second field"; } +#endif + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (full field). + added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Reset line number. + last_line = getSecondFieldLineNum(cur_field_order); + // Add lines from second field (cut data from the end). + added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); } } } @@ -5035,21 +5040,34 @@ void STC007DataStitcher::fillFrameForOutput() // Anchor B and anchor C are present. // No anchor A. // BC - if(target_lines_per_field==0) + // Calculate total number of lines for frame assembly. + lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.inner_padding+frasm_f1.outer_padding; + // Check line count according to video standard. + if((target_lines_per_field*2)>=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: BC, path: no limits"; + if((target_lines_per_field*2)==lines_to_fill) + { + qInfo()<<"[L2B-007] Data anchors: BC, path: frame size is correct"; + } + else + { + qInfo()<<"[L2B-007] Data anchors: BC, path: adding padding"; + } } #endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); + // Add padding up to frame standard. + added_inner = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); // Add lines from first field (full field). added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); + added_inner += addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); added_lines_cnt += added_inner; // Reset line number. last_line = getSecondFieldLineNum(cur_field_order); @@ -5061,68 +5079,28 @@ void STC007DataStitcher::fillFrameForOutput() } else { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.inner_padding+frasm_f1.outer_padding; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) - { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - if((target_lines_per_field*2)==lines_to_fill) - { - qInfo()<<"[L2B-007] Data anchors: BC, path: frame size is correct"; - } - else - { - qInfo()<<"[L2B-007] Data anchors: BC, path: adding padding"; - } - } -#endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add padding up to frame standard. - added_inner = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner += addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_anylog==false) { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: BC, path: too many lines, cutting first field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (cut data from the start). - added_lines_cnt += addLinesFromField(p_field_1, lines_to_fill, (field_1_cnt-lines_to_fill), &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - added_lines_cnt += added_outer; + qInfo()<<"[L2B-007] Data anchors: BC, path: too many lines, cutting first field"; } +#endif + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (cut data from the start). + added_lines_cnt += addLinesFromField(p_field_1, lines_to_fill, (field_1_cnt-lines_to_fill), &last_line); + // Add field-to-field padding. + added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); + added_lines_cnt += added_inner; + // Reset line number. + last_line = getSecondFieldLineNum(cur_field_order); + // Add lines from second field (full field). + added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); + // Add frame-to-frame padding. + added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); + added_lines_cnt += added_outer; } } else @@ -5130,15 +5108,19 @@ void STC007DataStitcher::fillFrameForOutput() // Anchor B present. // No anchor A and anchor C. // B - if(target_lines_per_field==0) + // Calculate total number of lines for frame assembly. + lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.inner_padding; + // Check line count according to video standard. + if((target_lines_per_field*2)>=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: B, path: no limits"; + qInfo()<<"[L2B-007] Data anchors: B, path: adding padding"; } #endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). @@ -5150,59 +5132,31 @@ void STC007DataStitcher::fillFrameForOutput() last_line = getSecondFieldLineNum(cur_field_order); // Add lines from second field (full field). added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); + // Add padding up to frame standard. + added_outer = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); + added_lines_cnt += added_outer; } else { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.inner_padding; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) - { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: B, path: adding padding"; - } -#endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add padding up to frame standard. - added_outer = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_anylog==false) { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: B, path: too many lines, cutting second field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add field-to-field padding. - added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (cut data from the end). - added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); + qInfo()<<"[L2B-007] Data anchors: B, path: too many lines, cutting second field"; } +#endif + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (full field). + added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Add field-to-field padding. + added_inner = addFieldPadding(frasm_f1.frame_number, frasm_f1.inner_padding, &last_line); + added_lines_cnt += added_inner; + // Reset line number. + last_line = getSecondFieldLineNum(cur_field_order); + // Add lines from second field (cut data from the end). + added_lines_cnt += addLinesFromField(p_field_2, 0, (field_2_cnt-lines_to_fill), &last_line); } } } @@ -5211,19 +5165,26 @@ void STC007DataStitcher::fillFrameForOutput() // Anchor C present. // No anchor A and anchor B. // C - if(target_lines_per_field==0) + // Calculate total number of lines for frame assembly. + lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.outer_padding; + // Check line count according to video standard. + if((target_lines_per_field*2)>=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: C, path: no limits"; + qInfo()<<"[L2B-007] Data anchors: C, path: adding padding"; } #endif + // Calculate number of padding lines to fill full frame. + lines_to_fill = (target_lines_per_field*2)-lines_to_fill; // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); // Add lines from first field (full field). added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Add padding up to frame standard. + added_inner = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); + added_lines_cnt += added_inner; // Reset line number. last_line = getSecondFieldLineNum(cur_field_order); // Add lines from second field (full field). @@ -5234,146 +5195,62 @@ void STC007DataStitcher::fillFrameForOutput() } else { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt+frasm_f1.outer_padding; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) - { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: C, path: adding padding"; - } -#endif - // Calculate number of padding lines to fill full frame. - lines_to_fill = (target_lines_per_field*2)-lines_to_fill; - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add padding up to frame standard. - added_inner = addFieldPadding(frasm_f1.frame_number, lines_to_fill, &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_anylog==false) { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: C, path: too many lines, cutting first field"; - } -#endif - // Calculate number of excess lines that should be cut. - lines_to_fill = lines_to_fill-(target_lines_per_field*2); - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (cut data from the end). - added_lines_cnt = addLinesFromField(p_field_1, 0, (field_1_cnt-lines_to_fill), &last_line); - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add frame-to-frame padding. - added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); - added_lines_cnt += added_outer; + qInfo()<<"[L2B-007] Data anchors: C, path: too many lines, cutting first field"; } +#endif + // Calculate number of excess lines that should be cut. + lines_to_fill = lines_to_fill-(target_lines_per_field*2); + // Reset line number. + last_line = getFirstFieldLineNum(cur_field_order); + // Add lines from first field (cut data from the end). + added_lines_cnt = addLinesFromField(p_field_1, 0, (field_1_cnt-lines_to_fill), &last_line); + // Reset line number. + last_line = getSecondFieldLineNum(cur_field_order); + // Add lines from second field (full field). + added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); + // Add frame-to-frame padding. + added_outer = addFieldPadding(frasm_f1.frame_number, frasm_f1.outer_padding, &last_line); + added_lines_cnt += added_outer; } } else { // No data anchors. - if(target_lines_per_field==0) + // Calculate total number of lines for frame assembly. + lines_to_fill = field_1_cnt+field_2_cnt; + // Check line count according to video standard. + if((target_lines_per_field*2)>=lines_to_fill) { - // Do not care about frame limits, assemble as is. #ifdef DI_EN_DBG_OUT if(suppress_anylog==false) { - qInfo()<<"[L2B-007] Data anchors: NONE, path: no limits"; + qInfo()<<"[L2B-007] Data anchors: NONE, path: adding padding"; } #endif // Reset line number. last_line = getFirstFieldLineNum(cur_field_order); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - } - else - { - // Calculate total number of lines for frame assembly. - lines_to_fill = field_1_cnt+field_2_cnt; - // Check line count according to video standard. - if((target_lines_per_field*2)>=lines_to_fill) + if((insert_top_line!=false)&&(field_1_cnt>0)&&(field_2_cnt>0)) { #ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: NONE, path: adding padding"; - } -#endif - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - if((insert_top_line!=false)&&(field_1_cnt>0)&&(field_2_cnt>0)) - { -#ifdef DI_EN_DBG_OUT - if(suppress_log==false) - { - if(insert_top_line!=false) - { - qInfo()<<"[L2B-007] One line shitfer enabled"; - } - } -#endif - // Need to add line above one field to fix noise. - if(cur_field_order==FrameAsmDescriptor::ORDER_BFF) - { - added_outer = addFieldPadding(frasm_f1.frame_number, 1, &last_line); - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Make next padding calculation one line less. - field_1_cnt++; - // Add padding up to field standard. - added_inner = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_1_cnt), &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Add padding up to field standard. - added_outer += addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_2_cnt), &last_line); - added_lines_cnt += added_outer; - } - else + if(suppress_log==false) + { + if(insert_top_line!=false) { - // Add lines from first field (full field). - added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); - // Add padding up to field standard (plus one line into next field to move next field data one line down). - added_inner = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_1_cnt+1), &last_line); - added_lines_cnt += added_inner; - // Reset line number. - last_line = getSecondFieldLineNum(cur_field_order); - // Add lines from second field (full field). - added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); - // Make next padding calculation one line less. - field_2_cnt++; - // Add padding up to field standard. - added_outer = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_2_cnt), &last_line); - added_lines_cnt += added_outer; + qInfo()<<"[L2B-007] One line shitfer enabled"; } } - else +#endif + // Need to add line above one field to fix noise. + if(cur_field_order==FrameAsmDescriptor::ORDER_BFF) { + added_outer = addFieldPadding(frasm_f1.frame_number, 1, &last_line); // Add lines from first field (full field). added_lines_cnt = addLinesFromField(p_field_1, 0, field_1_cnt, &last_line); + // Make next padding calculation one line less. + field_1_cnt++; // Add padding up to field standard. added_inner = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_1_cnt), &last_line); added_lines_cnt += added_inner; @@ -5382,49 +5259,81 @@ void STC007DataStitcher::fillFrameForOutput() // Add lines from second field (full field). added_lines_cnt += addLinesFromField(p_field_2, 0, field_2_cnt, &last_line); // Add padding up to field standard. - added_outer = addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_2_cnt), &last_line); + added_outer += addFieldPadding(frasm_f1.frame_number, (target_lines_per_field-field_2_cnt), &last_line); added_lines_cnt += added_outer; } - } - else - { -#ifdef DI_EN_DBG_OUT - if(suppress_anylog==false) - { - qInfo()<<"[L2B-007] Data anchors: NONE, path: too many lines"; - } -#endif - // Reset line number. - last_line = getFirstFieldLineNum(cur_field_order); - // Check if current frame field fits within standard limits. - if(field_1_cnt *in_queue) { bool suppress_log; uint8_t max_fixable; - uint16_t buf_size, buf_ofs, line_ofs, old_word, old_bitword, old_crc, word_patch_cnt, line_fix_cnt; + uint16_t buf_size, buf_ofs, line_ofs, line_fix_cnt; + uint16_t old_word, old_bitword, old_src_crc, old_clc_crc, word_patch_cnt; STC007DataBlock pcm_block; //return; @@ -5957,6 +5867,7 @@ uint16_t STC007DataStitcher::performCWD(std::deque *in_queue) // Set parameters for converter. lines_to_block.setInput(in_queue); lines_to_block.setOutput(&pcm_block); + //lines_to_block.setLogLevel(STC007Deinterleaver::LOG_PROCESS|STC007Deinterleaver::LOG_ERROR_CORR); lines_to_block.setIgnoreCRC(ignore_CRC); lines_to_block.setForceParity(!ignore_CRC); lines_to_block.setPCorrection(enable_P_code); @@ -5976,6 +5887,7 @@ uint16_t STC007DataStitcher::performCWD(std::deque *in_queue) // Fill up data block, performing de-interleaving, convert lines to data blocks. if(lines_to_block.processBlock(buf_ofs)!=STC007Deinterleaver::DI_RET_OK) { + // Exit cycle when not enough data left. break; } @@ -5991,8 +5903,9 @@ uint16_t STC007DataStitcher::performCWD(std::deque *in_queue) } // Check if data block is valid and samples were fixed. - if((pcm_block.isBlockValid()!=false)&&((pcm_block.isDataFixedByP()!=false)||(pcm_block.isDataFixedByQ()!=false))) + if((pcm_block.isBlockValid()!=false)&&(pcm_block.isDataFixed()!=false)) { + //qInfo()< *in_queue) if(suppress_log==false) { QString log_line; - log_line.sprintf("[L2B-007] Block [%03u-%03u...%03u-%03u] has fixed sample #%u from line [%03u-%03u]", + log_line.sprintf("[L2B-007] Block [%03u-%03u...%03u-%03u] has fixed sample #[%u] from line [%03u-%03u]", pcm_block.getStartFrame(), pcm_block.getStartLine(), pcm_block.getStopFrame(), @@ -6018,181 +5931,298 @@ uint16_t STC007DataStitcher::performCWD(std::deque *in_queue) } #endif // Check if source PCM line is not a filler one and has an invalid CRC in the first place. - if(((*in_queue)[line_ofs].isCRCValidIgnoreForced()==false)&&((*in_queue)[line_ofs].getSourceCRC()!=(0xFFFF&(~STC007Line::CRC_SILENT)))) + //if(((*in_queue)[line_ofs].isCRCValidIgnoreForced()==false)&&((*in_queue)[line_ofs].getSourceCRC()!=(0xFFFF&(~STC007Line::CRC_SILENT)))) + if(((*in_queue)[line_ofs].isCRCValidIgnoreForced()==false) + &&((*in_queue)[line_ofs].coords.areValid()!=false) + &&((*in_queue)[line_ofs].isForcedBad()==false) + &&((*in_queue)[line_ofs].frame_number!=frasm_f2.frame_number)) { - // Check if PCM line should not be fixed. - if((*in_queue)[line_ofs].isForcedBad()==false) + // Check audio sample resolution. + if(pcm_block.getResolution()==STC007DataBlock::RES_14BIT) { - // Check audio sample resolution. - if(pcm_block.getResolution()==STC007DataBlock::RES_14BIT) + // Propagate back corrections for 14-bit mode. + // Save old word content and old CRC for comparison. + old_word = (*in_queue)[line_ofs].getWord(word_idx); + old_src_crc = (*in_queue)[line_ofs].getSourceCRC(); + old_clc_crc = (*in_queue)[line_ofs].getCalculatedCRC(); + // Dump PCM line before patching. + //qInfo()<>STC007DataBlock::F1_WORD_OFS); // 14-bit MSB part. - // Move LSB bits. - if(word_idx==STC007DataBlock::WORD_P0) - { - new_bitword = (new_bitword<>STC007DataBlock::F1_WORD_OFS); // 14-bit MSB part. + // Move LSB bits. + if(word_idx==STC007DataBlock::WORD_P0) + { + new_bitword = (new_bitword< *in_queue) if(suppress_log==false) { QString log_line; - log_line.sprintf("[L2B-007] Replaced #%u word 0x%04x with 0x%04x in PCM line, PCM line [%03u-%03u] now has valid CRC 0x%04x (was 0x%04x)!!!", - word_idx, + log_line.sprintf("[L2B-007] Replaced #[%u] word [0x%04x] with [0x%04x] in PCM line, PCM line [%03u-%03u] now has valid CRC [0x%04x] (was [0x%04x])!!!", + STC007DataBlock::WORD_Q0, old_word, - new_word, + (*in_queue)[line_ofs].getWord(STC007DataBlock::WORD_Q0), (*in_queue)[line_ofs].frame_number, (*in_queue)[line_ofs].line_number, (*in_queue)[line_ofs].getCalculatedCRC(), - old_crc); + old_src_crc); qInfo()< *in_queue) if(suppress_log==false) { QString log_line; - log_line.sprintf("[L2B-007] Replaced #%u word 0x%04x with 0x%04x in PCM line, bad CRC 0x%04x remained bad as 0x%04x", - word_idx, + log_line.sprintf("[L2B-007] Replaced #[%u] word [0x%04x] with [0x%04x] in PCM line, bad CRC [0x%04x] remained bad as [0x%04x]", + STC007DataBlock::WORD_Q0, old_word, - new_word, - old_crc, + (*in_queue)[line_ofs].getWord(STC007DataBlock::WORD_Q0), + old_src_crc, (*in_queue)[line_ofs].getCalculatedCRC()); qInfo()<[0x%04x] in PCM line [%04u:%03u]!", + old_word, + (*in_queue)[line_ofs].getWord(word_idx), + (*in_queue)[line_ofs].frame_number, + (*in_queue)[line_ofs].line_number); + qInfo()< *in_queue) { qInfo()<<"[L2B-007] PCM line has good CRC and doesn't need to be fixed"; } + else if((*in_queue)[line_ofs].frame_number==frasm_f2.frame_number) + { + qInfo()<<"[L2B-007] PCM line is from the next frame, that line will be re-filled, skipping"; + } else { qInfo()<<"[L2B-007] PCM line is filler, that should not be fixed"; } } - } #endif - //qInfo()<isBlockValid(); + if(block_state==false) + { + word_left_fixed = word_right_fixed = false; + } + else + { + word_left_fixed = in_block->isWordLineCRCOk(STC007DataBlock::WORD_L0); + word_right_fixed = in_block->isWordLineCRCOk(STC007DataBlock::WORD_R0); + } word_left_state = in_block->isWordValid(STC007DataBlock::WORD_L0); word_right_state = in_block->isWordValid(STC007DataBlock::WORD_R0); } @@ -6545,16 +6516,28 @@ void STC007DataStitcher::outputDataBlock(STC007DataBlock *in_block) // Data block deemed to be "broken", no data can be taken as valid. block_state = false; word_left_state = word_right_state = false; + word_left_fixed = word_right_fixed = false; } // Set data to [PCMSamplePair] object. sample_pair.setSamplePair(in_block->getSample(STC007DataBlock::WORD_L0), in_block->getSample(STC007DataBlock::WORD_R0), - block_state, block_state, word_left_state, word_right_state); + block_state, block_state, + word_left_state, word_right_state, + word_left_fixed, word_right_fixed); // Put sample pair in the output queue. out_samples->push_back(sample_pair); // Output L1+R1 samples. if(in_block->isDataBroken()==false) { block_state = in_block->isBlockValid(); + if(block_state==false) + { + word_left_fixed = word_right_fixed = false; + } + else + { + word_left_fixed = in_block->isWordLineCRCOk(STC007DataBlock::WORD_L1); + word_right_fixed = in_block->isWordLineCRCOk(STC007DataBlock::WORD_R1); + } word_left_state = in_block->isWordValid(STC007DataBlock::WORD_L1); word_right_state = in_block->isWordValid(STC007DataBlock::WORD_R1); } @@ -6562,14 +6545,26 @@ void STC007DataStitcher::outputDataBlock(STC007DataBlock *in_block) { block_state = false; word_left_state = word_right_state = false; + word_left_fixed = word_right_fixed = false; } sample_pair.setSamplePair(in_block->getSample(STC007DataBlock::WORD_L1), in_block->getSample(STC007DataBlock::WORD_R1), - block_state, block_state, word_left_state, word_right_state); + block_state, block_state, + word_left_state, word_right_state, + word_left_fixed, word_right_fixed); out_samples->push_back(sample_pair); // Output L2+R2 samples. if(in_block->isDataBroken()==false) { block_state = in_block->isBlockValid(); + if(block_state==false) + { + word_left_fixed = word_right_fixed = false; + } + else + { + word_left_fixed = in_block->isWordLineCRCOk(STC007DataBlock::WORD_L2); + word_right_fixed = in_block->isWordLineCRCOk(STC007DataBlock::WORD_R2); + } word_left_state = in_block->isWordValid(STC007DataBlock::WORD_L2); word_right_state = in_block->isWordValid(STC007DataBlock::WORD_R2); } @@ -6577,9 +6572,12 @@ void STC007DataStitcher::outputDataBlock(STC007DataBlock *in_block) { block_state = false; word_left_state = word_right_state = false; + word_left_fixed = word_right_fixed = false; } sample_pair.setSamplePair(in_block->getSample(STC007DataBlock::WORD_L2), in_block->getSample(STC007DataBlock::WORD_R2), - block_state, block_state, word_left_state, word_right_state); + block_state, block_state, + word_left_state, word_right_state, + word_left_fixed, word_right_fixed); out_samples->push_back(sample_pair); mtx_samples->unlock(); @@ -6622,7 +6620,7 @@ void STC007DataStitcher::outputFileStop() size_t queue_size; if((out_samples==NULL)||(mtx_samples==NULL)) { - qWarning()<textDump()); + qInfo()<<"[DI-007] Stage"<dumpContentString()); } -#endif -*/ +#endif*/ + //qDebug()<<"[DI-007] State #"<markAsOriginalData(); // Count number of fills. fill_passes++; +#ifdef DI_EN_DBG_OUT + if((log_level&LOG_PROCESS)!=0) + { + qInfo()<<"[DI-007] Fill:"<dumpContentString()); + } +#endif // Go check CRC. proc_state = STG_ERROR_CHECK; } else if(proc_state==STG_ERROR_CHECK) { - bool skip_processing; - uint16_t p_code, q_code; - - skip_processing = false; // Preset "no index" value for error locators. first_bad = NO_ERR_INDEX; second_bad = NO_ERR_INDEX; // Reset "bad samples" counter. all_crc_errs = aud_crc_errs = 0; - if(run_audio_res==STC007DataBlock::RES_14BIT) + + // Search for audio samples with bad CRC. + for(uint8_t index=STC007DataBlock::WORD_L0;index<=STC007DataBlock::WORD_R2;index++) { - if(out_data_block->getErrorsTotalSource()==out_data_block->getErrorsAudioSource()) + if(out_data_block->isWordLineCRCOk(index)==false) { - // Both ECC words are intact (all errors in the audio part). - // Calculate P-word from actual audio samples. - p_code = calcPcode(out_data_block); - // Calculate Q-word for 14-bit mode. - q_code = calcQcode(out_data_block); - // Check if P&Q codes are the same in the data block, indicating no damage. - if((p_code==out_data_block->getWord(STC007DataBlock::WORD_P0))&& - (q_code==out_data_block->getWord(STC007DataBlock::WORD_Q0))&& - (out_data_block->getErrorsAudioSource()>2)) + // Count number of errors in audio samples. + if(first_bad==NO_ERR_INDEX) { - // No need to count and trace anything. - skip_processing = true; + // Save index of first error in audio data. + first_bad = index; } - } - } - /*else - { - // No Q-word for 16-bit mode. - if((p_code==out_data_block->getWord(STC007DataBlock::WORD_P0))&& - (out_data_block->getErrorsTotalSource()>0)) - { - // No need to count and trace anything. - skip_processing = true; - } - }*/ - - if(skip_processing==false) - { - // Search for audio samples with bad CRC. - for(uint8_t index=STC007DataBlock::WORD_L0;index<=STC007DataBlock::WORD_R2;index++) - { - if(out_data_block->isWordLineCRCOk(index)==false) + else if(second_bad==NO_ERR_INDEX) { - // Count number of errors in audio samples. - if(first_bad==NO_ERR_INDEX) - { - // Save index of first error in audio data. - first_bad = index; - } - else if(second_bad==NO_ERR_INDEX) - { - // Save index of second error in audio data. - second_bad = index; - break; - } + // Save index of second error in audio data. + second_bad = index; + break; } } - // Get number of words with bad CRC. - aud_crc_errs = out_data_block->getErrorsAudioSource(); - all_crc_errs = out_data_block->getErrorsTotalSource(); - proc_state = STG_TASK_SELECTION; - } - else - { -#ifdef DI_EN_DBG_OUT - if(suppress_log==false) - { - qInfo()<<"[DI-007] All words match up and good while indicated"<getErrorsTotalSource()<<"errors"; - } -#endif - // Mark all words as valid. - for(uint8_t index=STC007DataBlock::WORD_L0;index<=STC007DataBlock::WORD_Q0;index++) - { - out_data_block->setValid(index); - } - proc_state = STG_DATA_OK; } + // Get number of words with bad CRC. + aud_crc_errs = out_data_block->getErrorsAudioSource(); + all_crc_errs = out_data_block->getErrorsTotalSource(); + proc_state = STG_TASK_SELECTION; } else if(proc_state==STG_TASK_SELECTION) { @@ -802,10 +757,11 @@ uint8_t STC007Deinterleaver::processBlock(uint16_t line_shift) else if(fix_result==FIX_NOT_NEED) { // There was no actual error at the pointer. - /*if(first_badmarkAsFixedByP(); - }*/ + } #ifdef DI_EN_DBG_OUT if(suppress_log==false) { @@ -854,17 +810,33 @@ uint8_t STC007Deinterleaver::processBlock(uint16_t line_shift) // Q-code is damaged, fix it as well as soon as all other samples are fine. uint16_t q_code; q_code = calcQcode(out_data_block); -#ifdef DI_EN_DBG_OUT - if(suppress_log==false) + if(out_data_block->getWord(STC007DataBlock::WORD_Q0)!=q_code) { - QString log_line; - log_line.sprintf("[DI-007] Q-word is damaged, patching it: 0x%04u -> 0x%04u", - out_data_block->getWord(STC007DataBlock::WORD_Q0), q_code); - qInfo()<[0x%04x]", + out_data_block->getWord(STC007DataBlock::WORD_Q0), q_code); + qInfo()<setWord(STC007DataBlock::WORD_Q0, q_code, out_data_block->isWordLineCRCOk(STC007DataBlock::WORD_Q0), false); + // Mark Q-word as fixed. + out_data_block->setFixed(STC007DataBlock::WORD_Q0); } + else + { + // Mark Q-word as valid. + out_data_block->setValid(STC007DataBlock::WORD_Q0); +#ifdef DI_EN_DBG_OUT + if(suppress_log==false) + { + qInfo()<<"[DI-007] Q-word doesn't need fixing, updated to be valid"; + } #endif - out_data_block->setWord(STC007DataBlock::WORD_Q0, q_code, out_data_block->isWordLineCRCOk(STC007DataBlock::WORD_Q0), false); - out_data_block->setFixed(STC007DataBlock::WORD_Q0); + } } } } @@ -981,11 +953,11 @@ uint8_t STC007Deinterleaver::processBlock(uint16_t line_shift) // Clear "fixed by CWD" flags if present. out_data_block->clearWordFixedByCWD(first_bad); out_data_block->clearWordFixedByCWD(second_bad); - /*if(first_badmarkAsFixedByQ(); - }*/ + } #ifdef DI_EN_DBG_OUT if(suppress_log==false) { @@ -1109,7 +1081,7 @@ uint8_t STC007Deinterleaver::processBlock(uint16_t line_shift) else { #ifdef QT_VERSION - qWarning()<(STG_CONVERT_MAX*MAX_PASSES)) { #ifdef QT_VERSION - qWarning()<dumpContentString()); + } +#endif + // Store time that processing took. quint64 block_time; block_time = 0; @@ -1343,7 +1322,7 @@ void STC007Deinterleaver::recalcP(STC007DataBlock *data_block) if(suppress_log==false) { QString log_line; - log_line.sprintf("[DI-007] P-code updated 0x%04x -> 0x%04x and now valid", old_p, data_block->getWord(STC007DataBlock::WORD_P0)); + log_line.sprintf("[DI-007] P-code updated [0x%04x]->[0x%04x] and now valid", old_p, data_block->getWord(STC007DataBlock::WORD_P0)); qInfo()< 0x%04x", + log_line.sprintf("[DI-007] Syndrome for P-code: [0x%04x], bad sample at [%01u], fix: [0x%04x]->[0x%04x]", check, first_bad, data_block->getWord(first_bad), fix_word); qInfo()<setValid(first_bad); - //data_block->setFixed(first_bad); #ifdef DI_EN_DBG_OUT if(suppress_log==false) { @@ -1580,7 +1558,7 @@ uint8_t STC007Deinterleaver::fixByQ(STC007DataBlock *data_block, uint8_t first_b if(suppress_log==false) { QString log_line; - log_line.sprintf("[DI-007] ECC check failed (0x%04x, 0x%04x) while no CRC markers were set, broken block!", synd_p, synd_q); + log_line.sprintf("[DI-007] ECC check failed [0x%04x][0x%04x] while no CRC markers were set, broken block!", synd_p, synd_q); qInfo()< 0x%04x, 0x%04x^0x%04x -> 0x%04x", + log_line.sprintf("[DI-007] Bad samples at [%01u] and [%01u], fix: [0x%04x^0x%04x]->[0x%04x], [0x%04x^0x%04x]->[0x%04x]", first_bad, second_bad, old_word1, error_first, fix_word1, old_word2, error_second, fix_word2); @@ -2029,7 +2007,7 @@ uint8_t STC007Deinterleaver::fixByQ(STC007DataBlock *data_block, uint8_t first_b { // Error locator was not found. Probably bad branching due to incorrect input. #ifdef QT_VERSION - qWarning()< *in_vline, QMutex *m { if((in_vline==NULL)||(mtx_vline==NULL)) { - qWarning()< *out_pcmline, QMute { if((out_pcmline==NULL)||(mtx_pcmline==NULL)) { - qWarning()< *out_pcmli { if((out_pcmline==NULL)||(mtx_pcmline==NULL)) { - qWarning()< *out_pcmline, Q { if((out_pcmline==NULL)||(mtx_pcmline==NULL)) { - qWarning()<start(); + ffmpeg_thread->start(QThread::HighPriority); // Inf. loop in a thread. while(finish_work==false) @@ -1367,6 +1368,7 @@ void VideoInFFMPEG::captureReady(int in_width, int in_height, uint32_t in_frames #endif evt_frame_cnt = in_frames; event_cap |= EVT_CAP_OPEN; + src_open = true; } @@ -1380,6 +1382,7 @@ void VideoInFFMPEG::captureClosed() } #endif event_cap |= EVT_CAP_CLOSE; + src_open = false; } //------------------------ Something went wrong with capture process. diff --git a/vin_ffmpeg.h b/vin_ffmpeg.h index 0cd54da..725f3f5 100644 --- a/vin_ffmpeg.h +++ b/vin_ffmpeg.h @@ -112,6 +112,7 @@ class VideoInFFMPEG : public QObject QThread *ffmpeg_thread; // Thread for FFMPEG wrapper. FFMPEGWrapper *ffmpeg_src; // FFMPEG Qt-wrapper. bool new_file; // Is this the first frame of a new source? + bool src_open; // Is source open and ready? bool step_play; // Enable or disable auto-pause after each frame. bool detect_frame_drop; // Detect dropouts via PTS or not? bool finish_work; // Flag to break executing loop.