Как отобразить декодированный буфер из ffmpeg в QVideoFrame? - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь поместить декодированный буфер ffmpeg в QFrame, чтобы я мог поместить этот кадр в QAbstractVideoBuffer, а затем поместить этот буфер в QMediaPlayer.

Вот код для VideoSurface.Согласно документации QT, мне просто нужно реализовать эти две функции: конструктор и bool present, который обрабатывает фрейм в QVideoFrame с именем frame

QList<QVideoFrame::PixelFormat> VideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const
{
    Q_UNUSED(handleType);

    // Return the formats you will support
    return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_YUV420P;
}

bool VideoSurface::present(const QVideoFrame &frame)
{
    //Q_UNUSED(frame);
    std:: cout << "VideoSurface processing 1 frame " << std::endl; 

    QVideoFrame frametodraw(frame);

    if(!frametodraw.map(QAbstractVideoBuffer::ReadOnly))
    {
        setError(ResourceError);
        return false;
    } 
    // Handle the frame and do your processing
    const size_t bufferSize = 398304;
    uint8_t frameBuffer[bufferSize];
    this->mediaStream->receiveFrame(frameBuffer, bufferSize);
    //Frame is now in frameBuffer, we must put into frametodraw, I guess
    // ------------What should I do here?-------------
    frametodraw.unmap();
    return true;
}

Посмотрите на this->mediaStream.decodeFrame(frameBuffer, bufferSize).Эта строка декодирует новый кадр h264 в frameBuffer в формате YUV420P.

Моя идея состояла в том, чтобы использовать функцию map, а затем попытаться получить указатель буфера с помощью функции frametodraw.bits() и попытаться указать этоуказатель на другую вещь, но я не думаю, что это путь.Я думаю, что я должен скопировать содержимое frameBuffer в этот указатель, но этот указатель, например, не сообщает мне о его размере, поэтому я думаю, что это также не так.

Итак ... Какя должен отобразить свой буфер в QVideoFrame с именем frame?

Я также заметил, что когда я помещаю свой экземпляр VideoSurface в мой QMediaPlayer, present никогда не вызывается.Я думаю, что-то не так, даже с player->play() Это важно .

У меня также нет размера декодированного изображения внутри frameBuffer, у меня есть только его общий размер.Я думаю, что это также должно быть проблемой.

Я также заметил, что QMediaPlayer не является отображаемым элементом ... Так какой виджет будет отображать мое видео?Это кажется мне важным.

1 Ответ

0 голосов
/ 16 февраля 2019

Я думаю, вы неправильно понимаете роль каждого класса.Вы создаете подкласс QAbstractVideoSurface, и он должен помочь с доступом к данным, которые готовы для представления.Внутри представленного метода вам предоставляется уже декодированный QVideoFrame.Если вы хотите отобразить это на экране, вам нужно реализовать его в классе VideoSurface.

Вы можете установить VideoSurface на QMediaPlayer, и медиаплеер уже обрабатывает декодирование видео и согласованиеформат пикселей.Тот QVideoFrame, который вы получаете в подарок от VideoSurface, уже имеет высоту / ширину и формат пикселей от медиаплеера.Типичное использование медиапроигрывателя - загружать и декодировать файлы, отображать их на экране вместе с виджетом видео.

Если вам требуется использовать свой собственный декодер ffmpeg, мой совет - преобразовать кадр из yuv420 в rgb (libswscale?), Создать свой собственный пользовательский виджет, который вы также можете передавать данные кадра, и вы можете отрендеритьэто на экране с использованием QPainter после загрузки его в QPixmap.

...