Команды FFmpeg: от новичка до профессионала | Процесс декодирования FFmpeg
Команды FFmpeg: от новичка до профессионала | Процесс декодирования FFmpeg
Этот контент относится к руководству по FFmpeg доктора Лэй Сяохуа.
блок-схема
Блок-схема декодирования FFmpeg выглядит следующим образом:
Процесс декодирования FFmpeg:
- Регистрация:
Чтобы использовать библиотеки, соответствующие ffmpeg, вам необходимо зарегистрироваться. Вы можете зарегистрировать подпункты или все из них. - Открыть файл:
откройте файл и получите соответствующий глобальный контекст ffmpeg на основе информации об имени файла. - Обнаружение информации о потоке:
обязательно определите информацию о потоке и получите формат кодирования потока. Если вы не обнаружите информацию о потоке, тип кодирования, полученный кодировщиком потока, может быть пустым. Исходный формат не будет известен во время последующее преобразование данных, приводящее к ошибкам. - Найдите соответствующий декодер:
Найдите декодер по формату потока. Здесь решается мягкое или жесткое декодирование, но обратите особое внимание на то, поддерживается ли оборудование. Вам необходимо найти идентификатор, соответствующий локальному аппаратному декодеру, и проверить поддерживает ли он это. Обычной операцией является перечисление всех декодеров, поддерживающих декодирование суффиксов файлов, и их поиск.Как только они найдены, их можно жестко декодировать (я не буду здесь слишком подробно обсуждать, для дальнейшего исследования будут статьи по жесткому декодированию). (Примечание. Ищите декодер при декодировании и ищите кодировщик при кодировании. Функции этих двух разных, не делайте ошибку, иначе вы можете открыть его позже, но данные будут неправильными) - Открыть декодер:
открыть полученный декодер. - Применить структуру преобразования формата масштабируемых данных: обратите
здесь особое внимание.По сути, декодированные данные имеют формат серии yuv, но данные, которые мы отображаем, представляют собой данные в связанных цветовых пространствах, таких как RGB, поэтому структура преобразования здесь заключается в выполнении преобразования до и после преобразования. Следующее описание обеспечивает основу транскодирования для последующих функций преобразования. Это очень важная и очень часто используемая структура. - Подайте заявку на буферную область:
подайте заявку на буферную область outBuffer, заполните ее данными наших целевых данных кадра, такими как данные RGB, данные QAVFrame хранят данные в указанном формате, а правила хранения существуют, и заполните их. в outBuffer (цель, на которую вы подали заявку) Формат (область буфера кадра) — это необходимый нам порядок хранения формата данных.
Например, декодированные и преобразованные данные — это rgb888. На самом деле неправильно использовать данные данных напрямую, но правильно использовать outBuffer, поэтому функция заполнения ffmpeg должна выполнить здесь некоторое преобразование.
Введите декодирование цикла: - Получить кадр пакета:
получить инкапсулированный пакет, определить тип данных пакета, декодировать его и получить сохраненные закодированные данные. - Преобразование данных:
используйте функцию преобразования в сочетании со структурой преобразования для преобразования закодированных данных, а затем получите необходимую целевую ширину, высоту и исходные данные в указанном формате хранения. - Обработка самостоятельно:
получите исходные данные и обработайте их самостоятельно. Продолжайте цикл до тех пор, пока функция packcet не будет успешно получена, но один кадр данных не может быть получен, что означает, что декодирование файла завершено. Частоту кадров нужно шлейфом контролировать самостоятельно, здесь просто получение шлейфа, а можно добавлять задержки и т.д. - Выпуск QAVPacket:
он указан здесь отдельно, потому что на самом деле многие онлайн-коды и коды разработчиков выполняют av_new_packet перед входом в циклическое декодирование, но не выполняют av_free_packet в цикле, вызывая переполнение памяти; или выполняют av_new_packet перед входом в циклическое декодирование, и цикл Если в программе выполняется av_free_pakcet, то одному новому соответствует бесчисленное количество свободных, что не соответствует спецификации соответствия «один к одному» на кодировщике. Глядя на исходный код, вы действительно можете обнаружить, что при av_read_frame автоматически выполняется av_new_packet(), поэтому фактически для пакета вам нужно выполнить av_packet_alloc() только один раз, и av_free_packet завершается после декодирования.
После завершения выполнения вернитесь к «Шагу 8: Получение кадра пакета», и цикл завершится. - Освободите структуру преобразования:
после завершения декодирования устанавливается последовательность приложений и высвобождаются соответствующие ресурсы. - Закрыть декодер/кодер:
Закройте ранее открытый декодер/кодер. - Закрытие контекста:
После закрытия контекста файла ранее примененные переменные должны быть освобождены в порядке их применения.
Функция декодирования FFmpeg
- av_register_all(): Зарегистрируйте все компоненты.
- avformat_open_input(): открыть входной видеофайл.
- avformat_find_stream_info(): Получить информацию о видеофайле.
- avcodec_find_decoder(): Найдите декодер.
- avcodec_open2(): открыть декодер.
- av_read_frame(): считывает кадр сжатых данных из входного файла.
- avcodec_decode_video2(): декодирует кадр сжатых данных.
- avcodec_close(): закрывает декодер.
- avformat_close_input(): закрывает входной видеофайл.
Структура данных, декодированная FFmpeg
Структура данных, декодированная FFmpeg, выглядит следующим образом:
Структура данных FFmpeg:
- AVFormatContext: Структура контекста формата инкапсуляции также является общей структурой, которая сохраняет информацию, относящуюся к формату инкапсуляции видеофайла.
- AVInputFormat: каждому формату упаковки (например, FLV, MKV, MP4, AVI) соответствует одна структура.
- AVStream: Каждый видео(аудио)поток в видеофайле соответствует одной структуре.
- AVCodecContext: структура контекста кодировщика, которая сохраняет информацию, связанную с кодированием и декодированием видео (аудио).
- AVCodec: каждый видео-(аудио) кодек (например, декодер H.264) соответствует одной структуре.
- AVPacket: хранит один кадр сжатых закодированных данных.
- AVFrame: хранит один кадр декодированных данных пикселей (выборки).
Анализ структуры данных FFmpeg:
AVFormatContext:
- iformat: AVInputFormat входного видео
- nb_streams: количество AVStreams входного видео.
- потоки: AVStream[] массив входного видео
- продолжительность: продолжительность входного видео (в микросекундах).
- bit_rate: битрейт входного видео
AVInputFormat:
- name: имя формата пакета
- long_name: длинное имя инкапсулированного формата.
- расширения: расширение инкапсулированного формата
- id: идентификатор формата инкапсуляции
- Некоторые функции интерфейса для обработки формата пакета
AV-поток:
- идентификатор: серийный номер
- кодек: AVCodecContext, соответствующий этому потоку
- time_base: временная база потока
- r_frame_rate: частота кадров этого потока.
AVCodecContext:
- кодек: AVCodec кодека
- ширина, высота: ширина и высота изображения (только для видео)
- pix_fmt: формат пикселей (только для видео)
- sample_rate: частота дискретизации (только для аудио)
- каналы: количество каналов (только для звука)
- sample_fmt: формат выборки (только для аудио)
AV-кодек:
- имя: имя кодека
- long_name: длинное имя кодека
- тип: тип кодека
- идентификатор: идентификатор кодека
- Некоторые функции интерфейса кодирования и декодирования
AV-пакет:
- pts: отображать временную метку
- dts: временная метка декодирования
- данные: сжатые закодированные данные
- размер: размер сжатых закодированных данных.
- stream_index: дочерний AVStream
AVFrame:
- данные: данные пикселей декодированного изображения (данные выборки звука).
- linesize: для видео — это размер строки пикселей изображения; для аудио — это размер всего аудиокадра.
- ширина, высота: ширина и высота изображения (только для видео).
- key_frame: является ли это ключевым кадром (только для видео).
- pict_type: тип кадра (только для видео). Например, Я, П, Б.
Дополнительные знания
Почему декодированные данные необходимо обрабатывать функцией sws_scale()?
Декодированные данные видеопикселей в формате YUV хранятся в data[0], data[1] и data[2] AVFrame. Однако эти значения пикселей не сохраняются постоянно, и некоторые недействительные пиксели сохраняются после каждой строки действительных пикселей. Если взять в качестве примера данные яркости Y, data[0] содержит в общей сложности данные linesize[0]*height. Однако из-за оптимизации и других соображений, linesize[0] на самом деле не равен ширине, а является значением, превышающим ширину. Поэтому вам нужно использовать sws_scale() для преобразования. После преобразования недопустимые данные удаляются, а ширина и размер строки[0] имеют равные значения.