Arhn - архитектура программирования

Декодировать видеофайл из памяти с помощью libav

Предположим, у меня есть целый видеофайл в памяти, и я хочу использовать libav для декодирования целых кадров. Как я должен это делать? Дело в том, что я могу сделать это, читая прямо из файла, используя функцию avformat_open_input(), но мне нужно сделать это из файла, который хранится в памяти.

Моя реализация AVIOContext:

class AVIOMemContext
{

public:

    AVIOMemContext(char* videoData, const int videoLen)
    {
        // Output buffer
        bufferSize = 32768;
        buffer = static_cast<char*>(av_malloc(bufferSize));

        // Internal buffer
        pos = 0;
        this->videoData = videoData;
        this->videoLen = videoLen;

        ctx_ = avio_alloc_context((unsigned char*) buffer, bufferSize, AVIO_FLAG_READ, this, &AVIOMemContext::read, &AVIOMemContext::write, &AVIOMemContext::seek);
    }

    ~AVIOMemContext()
    {
        av_free(videoData);
    }

    static int read(void *opaque, unsigned char *buf, int buf_size)
    {
        AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque);

        // Read from pos to pos + buf_size
        if (This->pos + buf_size > This->videoLen)
        {
            int len = This->videoLen - This->pos;
            memcpy(buf, This->videoData + This->pos, len);
            return len;
        }
        else
        {
            memcpy(buf, This->videoData + This->pos, buf_size);
            return buf_size;
        }
    }

    static int write(void *opaque, unsigned char *buf, int buf_size)
    {
        /*
        AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque);
        return fwrite(buf, 1, buf_size, This->f_);
        */

        return 0;
    }

    static int64_t seek(void *opaque, int64_t offset, int whence)
    {
        AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque);

        if (offset + whence > This->videoLen)
        {
            This->pos = This->videoLen;

            return -1;
        }
        else
        {
            This->pos = offset + whence;

            return 0;
        }
    }

    AVIOContext *get_avio()
    {
        return ctx_;
    }

private:

    // Output buffer
    int bufferSize;
    char* buffer;

    // Internal buffer
    int pos;
    char* videoData;
    int videoLen;

    AVIOContext* ctx_;

};

Мой текущий код:

[...]

av_register_all();
avcodec_register_all();

AVFormatContext* context;
AVCodec* pCodec;
AVPacket packet;
AVCodecContext* pCodecCtx;
int video_stream_index;
int res;
int got_picture;

// Init variables and objects
context = avformat_alloc_context();

AVIOMemContext priv_ctx(videoData, videoLen); 
context->pb = priv_ctx.get_avio();

res = avformat_find_stream_info(context, NULL);

if (res < 0)
{
    // Error
    avformat_free_context(context);

    return 0;
}

// Obtain the video stream of the total set of streams
for (unsigned int k = 0; k < context->nb_streams; ++k)
{
    if (context->streams[k]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        video_stream_index = k;
    context->streams[k]->codec->time_base.den = 90000;
}

pCodecCtx = context->streams[video_stream_index]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

avcodec_open(pCodecCtx, pCodec);

//allocate video frame
AVFrame *pFrame = avcodec_alloc_frame();

unsigned int nFrame = 0;

while (av_read_frame(context, &packet) >= 0)

[...]

Заранее спасибо,

Дидак Перес

12.12.2012

Ответы:


1

Вы можете создать свой собственный AVIOContext. Вы должны позвонить ::avio_alloc_context, а затем установить его на AVFormatContext::pb. Подробнее см. в моем ответе на Как можно ли использовать libavformat без использования других библиотек libav?

12.12.2012
  • В настоящее время я создал свой собственный AVIOContext, но приложение вылетает в avformat_find_stream_info() 12.12.2012
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..