Образец FFMPEG remux без записи в файл - PullRequest
1 голос
/ 27 января 2020

Давайте рассмотрим этот очень хороший и простой в использовании пример remux от horgh .

Я бы хотел решить ту же задачу: преобразовать кодированный поток RTSP H264 в фрагментированный поток MP4 , Этот код выполняет именно эту задачу.

Однако я вообще не хочу записывать mp4 на диск, но мне нужно получить байтовый буфер или массив в C с содержимым, которое обычно записывается в диск.

Как это возможно? В этом примере vs_open_output используется для определения выходного формата, а для этой функции необходим выходной URL.

Если бы я избавился от вывода содержимого на диск, как мне изменить этот код? Или, возможно, есть и лучшие альтернативы, которые также приветствуются.

Обновление:

Как рекомендовал szatmary, я проверил его пример ссылки .

Однако, как я уже сказал в вопросе, мне нужен вывод в виде буфера, а не файла. Этот пример наглядно демонстрирует, как я могу прочесть свой пользовательский источник и передать его в ffmpeg.

Что мне нужно, так это как открыть входные данные в стандартном режиме (с помощью avformat_open_input ), а затем выполнить мои пользовательские изменения с помощью пакеты и затем вместо записи в файл, записи в буфер.

Что я пробовал?

На основе примера szatmary я создал несколько буферов и инициализацию:

uint8_t *buffer;
buffer = (uint8_t *)av_malloc(4096);

format_ctx = avformat_alloc_context();
format_ctx->pb = avio_alloc_context(
                buffer, 4096, // internal buffer and its size
                1,            // write flag (1=true, 0=false)
                opaque,  // user data, will be passed to our callback functions
                0,      // no read
                &IOWriteFunc,
                &IOSeekFunc
);
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; 

AVOutputFormat * const output_format = av_guess_format("mp4", NULL, NULL);
format_ctx->oformat = output_format;

avformat_alloc_output_context2(&format_ctx, output_format,
            NULL, NULL)

Затем, конечно, я создал 'IOWriteFun c' и 'IOSeekFun c':

static int IOWriteFunc(void *opaque, uint8_t *buf, int buf_size) {
    printf("Bytes read: %d\n", buf_size);
    int len = buf_size;
    return (int)len;
}

static int64_t IOSeekFunc (void *opaque, int64_t offset, int whence) {
    switch(whence){
        case SEEK_SET:
            return 1;
            break;
        case SEEK_CUR:
            return 1;
            break;
        case SEEK_END:
            return 1;
            break;
        case AVSEEK_SIZE:
            return 4096;
            break;
        default:
           return -1;
    }
    return 1;
}

Затем мне нужно записать заголовок в выходной буфер, и ожидаемое поведение здесь - напечатать "Чтение байтов: x" :

AVDictionary * opts = NULL;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
av_dict_set_int(&opts, "flush_packets", 1, 0);

avformat_write_header(output->format_ctx, &opts)

В последней строке во время выполнения всегда возникает ошибка seg, вот обратная трассировка:

#0  0x00007ffff7a6ee30 in  () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
#1  0x00007ffff7a98189 in avformat_init_output () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
#2  0x00007ffff7a98ca5 in avformat_write_header () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
...

Трудно для меня с примером в том, что он использует avformat_open_input .

Однако такого вывода для вывода не существует (нет avformat_open_ouput ).

Update2:

Я нашел Ano Пример для чтения: doc / examples / avio_reading. c.

Есть упоминания о похожем примере для записи (avio_writing. c), но ffmpeg не имеет этого доступно (по крайней мере, в моем поиске Google).

Эта задача действительно трудно решить? стандартный ввод rtsp для пользовательского avio?

К счастью, ffmpeg.org не работает. Отлично.

Ответы [ 2 ]

1 голос
/ 31 января 2020

Это была глупая ошибка:

В части инициализации я назвал это:

avformat_alloc_output_context2(&format_ctx, output_format,
        NULL, NULL)

Однако до этого я уже помещал буферы avio в format_ctx:

format_ctx->pb = ...

Кроме того, эта строка не нужна:

format_ctx = avformat_alloc_context();

Правильный порядок:

AVOutputFormat * const output_format = av_guess_format("mp4", NULL, NULL);

avformat_alloc_output_context2(&format_ctx, output_format,
            NULL, NULL)

format_ctx->pb = avio_alloc_context(
                buffer, 4096, // internal buffer and its size
                1,            // write flag (1=true, 0=false)
                opaque,  // user data, will be passed to our callback functions
                0,      // no read
                &IOWriteFunc,
                &IOSeekFunc
);
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO; 
format_ctx->oformat = output_format; //might be unncessary too

Сегфоут исчезла.

1 голос
/ 28 января 2020

Вам необходимо написать реализацию AVIOContext.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...