Как я могу мультиплексировать поток H264 в файл MP4 через libavformat

Я хочу реализовать приложение, которое сначала декодирует мультимедийный файл (например, файл test.mp4, идентификатор видеокодека - H264), получает видеопоток и аудиопоток, а затем делает несколько разных аудиопотоков, наконец, кодирует видеопоток (используйте libx264) и аудиопоток в файл результата (result.mp4). Чтобы повысить эффективность, я опустил декодирование и кодирование видеопотока, я получаю видеопакет с помощью функции «av_read_frame», а затем вывожу его непосредственно в файл результата с помощью функции «av_write_frame». Но в выходном файле нет изображения, и размер выходного файла довольно мал.

Я отследил код ffmpeg и обнаружил, что в функции «av_write_frame->mov_write_packet->ff_mov_write_packet» будет вызываться функция «ff_avc_parse_nal_units», чтобы получить размер конечной единицы, но возвращаемое значение очень маленькое (например, 208 байт).

Я обнаружил, что поток H264 в файле MP4 не хранится в формате Приложения-B, поэтому он не может найти начальный код (0x000001), теперь моя проблема заключается в том, как я могу изменить поток H264 на формат Приложения-B и сделать Это работает?Я добавил стартовый код в начале каждого кадра вручную, но это все еще не работает.

Кто-нибудь может дать мне подсказку? Большое спасибо. Ниже приведены коды, похожие на мой:

    // write the stream header, if any
    av_write_header(pFormatCtxEnc);

    .........
    /**
    * Init of Encoder and Decoder
    */

    bool KeyFlag = false;
    bool KeyFlagEx = false;
    // Read frames and save frames to disk
    int iPts = 1;
    av_init_packet(&packet);
    while(av_read_frame(pFormatCtxDec, &packet)>=0)
    {
            if (packet.flags == 1)
                    KeyFlag = true;

            if (!KeyFlag)
                    continue;

            if (m_bStop)
            {
                    break;
            }

            // Is this a packet from the video stream?
            if(packet.stream_index == videoStream)
            {
                    currentframeNum ++;
                    if (progressCB != NULL && currentframeNum%20 == 0)
                    {
                            float fpercent = (float)currentframeNum/frameNum;
                            progressCB(fpercent,m_pUser);
                    }

                    if (currentframeNum >= beginFrame && currentframeNum <= endFrane)
                    {
                            if (packet.flags == 1)
                                    KeyFlagEx = true;

                            if (!KeyFlagEx)
                                    continue;
                            packet.dts = iPts ++;
                            av_write_frame(pFormatCtxEnc, &packet);

                    }
            }
            // Free the packet that was allocated by av_read_frame
    }

    // write the trailer, if any
    av_write_trailer(pFormatCtxEnc);

    /**
    * Release of encoder and decoder
    */

    return true;

person Brian    schedule 27.12.2012    source источник
comment
Мультиплексор MP4 FFmpeg можно настроить на прием потоков как со стартовыми кодами, так и без них. Начальные NAL обычно представляют собой наборы параметров и могут быть небольшими. av_write_frame это правильно. Какой у вас код? Может кто заметит проблему.   -  person Roman R.    schedule 27.12.2012
comment
Спасибо, как настроить мультиплексор MP4 ffmpeg для приема потоков без стартового кода? Нужно ли устанавливать какие-то специальные параметры? Вышеприведенные коды похожи на мой. Возвращаемое значение функции ff_avc_parse_nal_units равно почти 0 для каждого кадра, и большинство кадров выводятся без результата.   -  person Brian    schedule 28.12.2012
comment
@ Брайан, ты уже нашел какое-нибудь решение для этого?   -  person Wang    schedule 10.05.2019


Ответы (1)


Вы можете попробовать это: libavcodec/h264_mp4toannexb_bsf.c. Он преобразует битовый поток без стартовых кодов в битовый поток со стартовыми кодами.

Используя ваш исходный файл, работает ли ffmpeg -i src.mp4 -vcodec copy -an dst.mp4? Будет ли работать, если вы добавите -bsf h264_mp4toannexb? (все используют ту же версию/сборку ffmpeg, что и вы, конечно, пытаетесь использовать программно)

person Alex I    schedule 06.01.2013
comment
это mp4 к приложениюb, но не приложениеb к mp4 - person Wang; 10.05.2019