Java NAL в H264

Кто-нибудь когда-нибудь использовал хорошую библиотеку Java с открытым исходным кодом, которая позволяла бы конвертировать NAL > H264?

Я видел много библиотек, но большинство из них неполные или очень сложные в использовании (отсутствие документации и т. д.).

Я хочу передать полезную нагрузку NAL и получить фактическое необработанное видео H.264. Следующим шагом будет размещение этого в контейнере MP4.


person Display Name    schedule 14.08.2012    source источник


Ответы (2)


Из обсуждения в комментариях я перефразирую ваш вопрос и разделю его на два:

Я хочу извлечь блоки NAL из пакетов RTP H264 в чистом java и сбросить их в файл H264 приложения B.

Как я могу это сделать? Есть ли библиотека?

Полезная нагрузка этих пакетов указана в RFC3984.

Я не знаю какой-либо библиотеки Java, которая выполняет это из коробки. Но реализация довольно проста, если тип упаковки не чередуется:

RFC3984 допускает три типа упаковки

  • Режим одного блока NAL
  • Режим без чередования
  • Режим чередования

пока ваш источник пакетов отправляет в режиме одиночных блоков NAL или в режиме без чередования, вы можете извлекать блоки NAL без какой-либо дальнейшей обработки из пакетов и выгружать их на диск с 0x00,0x00,0x00,0x01 в качестве разделителя между ними.

Если тип упаковки чередуется, вам нужно приложить гораздо больше усилий, чем вам придется заглянуть в NAL и переупорядочить их, чтобы они были в порядке декодирования.

Я мультиплексирую необработанные файлы H264 Приложения B в контейнер MP4 на чистой Java.

Вы можете использовать мой проект mp4parser для создания MP4 из формата Приложения B. Взгляните на H264Example — это должно дать вам представление о том, как его использовать.

person Sebastian Annies    schedule 14.08.2012
comment
Я с нетерпением жду возможности извлечь необработанный H264 из полезной нагрузки RTP. Может ли mp4parser помочь в этом? Или вы знаете о других инструментах? - person Display Name; 15.08.2012
comment
Нет, mp4parser вам в этом не поможет. Это может помочь только в создании MP4 из необработанного потока H264. ietf.org/rfc/rfc3984.txt описывает, как Nals H264 упаковываются в сообщения RTP. . Извлечь их не должно быть проблемой. Проблема может возникнуть, если им потребуется изменить порядок, но я не уверен, что это необходимо. - person Sebastian Annies; 15.08.2012
comment
Почему меня минусовали? Я хотел бы улучшить свою публикацию - дайте мне шанс. Я думаю, что предоставил ценную информацию «Отображаемому имени», и да, мой инструмент может ему помочь. Является ли реклама моей библиотеки причиной отрицательного голоса? - person Sebastian Annies; 15.08.2012
comment
Спасибо за вклад, я только что проголосовал за вас, не знаю, кто/почему проголосовал за вас. Знаете ли вы о какой-либо библиотеке, которая обрабатывает преобразование NAL в H.264? - person Display Name; 16.08.2012
comment
Итак, если вы говорите о преобразовании NAL в H.264, вы на самом деле говорите об извлечении блоков NAL из полезной нагрузки RTP? - person Sebastian Annies; 16.08.2012
comment
да. Извлечение NAL и добавление правильного содержимого NAL (и не только, см. префикс NAL) для получения допустимого необработанного потока H.264, который впоследствии может быть использован mp4parser для создания файла MP4. - person Display Name; 16.08.2012
comment
Извлечение блоков NAL H.264 из потока RTP довольно тривиально. См. RFC 3984 спецификацию полезной нагрузки H.264 RTP. - person jgh; 16.08.2012

Вот что я нашел в примерах JCodec ( http://jcodec.org ):

public class AVCMP4Mux {
    private static AvcCBox avcC;

    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            System.out.println("Syntax: <in.264> <out.mp4>\n" + "\tWhere:\n"
                    + "\t-q\tLook for stream parameters only in the beginning of stream");
            return;
        }

        File in = new File(args[0]);
        File out = new File(args[1]);

        SeekableByteChannel file = writableFileChannel(out);
        MP4Muxer muxer = new MP4Muxer(file);
        CompressedTrack track = muxer.addTrackForCompressed(TrackType.VIDEO, 25);

        mux(track, in);

        muxer.writeHeader();

        file.close();
    }

    private static void mux(CompressedTrack track, File f) throws IOException {
        MappedH264ES es = new MappedH264ES(NIOUtils.map(f));

        ArrayList<ByteBuffer> spsList = new ArrayList<ByteBuffer>();
        ArrayList<ByteBuffer> ppsList = new ArrayList<ByteBuffer>();
        Packet frame = null;
        while ((frame = es.nextFrame()) != null) {
            ByteBuffer wrap = frame.getData().duplicate();
            H264Utils.encodeMOVPacket(wrap, spsList, ppsList);
            MP4Packet pkt = new MP4Packet(new Packet(frame, wrap), frame.getPts(), 0);
            System.out.println(pkt.getFrameNo());
            track.addFrame(pkt);
        }
        addSampleEntry(track, es.getSps(), es.getPps());
    }

    private static void addSampleEntry(CompressedTrack track, SeqParameterSet[] spss, PictureParameterSet[] ppss) {
        SeqParameterSet sps = spss[0];
        Size size = new Size((sps.pic_width_in_mbs_minus1 + 1) << 4, getPicHeightInMbs(sps) << 4);

        SampleEntry se = MP4Muxer.videoSampleEntry("avc1", size, "JCodec");

        avcC = new AvcCBox(sps.profile_idc, 0, sps.level_idc, write(spss), write(ppss));
        se.add(avcC);
        track.addSampleEntry(se);
    }

    private static List<ByteBuffer> write(PictureParameterSet[] ppss) {
        List<ByteBuffer> result = new ArrayList<ByteBuffer>();
        for (PictureParameterSet pps : ppss) {
            ByteBuffer buf = ByteBuffer.allocate(1024);
            pps.write(buf);
            buf.flip();
            result.add(buf);
        }
        return result;
    }

    private static List<ByteBuffer> write(SeqParameterSet[] spss) {
        List<ByteBuffer> result = new ArrayList<ByteBuffer>();
        for (SeqParameterSet sps : spss) {
            ByteBuffer buf = ByteBuffer.allocate(1024);
            sps.write(buf);
            buf.flip();
            result.add(buf);
        }
        return result;
    }
}

Я взял это отсюда: https://github.com/jcodec/jcodec/blob/master/samples/main/java/org/jcodec/samples/mux/AVCMP4Mux.java

person Stanislav Vitvitskyy    schedule 22.05.2013