используя FFmpeg, как декодировать пакеты H264

Я новичок в FFmpeg и изо всех сил пытаюсь декодировать пакеты H264, которые можно получить в виде массива uint8_t.

После многих исследований я думаю, что он должен просто поместить массив в AVPacket, как показано ниже.

AVPacket *avpkt = (AVPacket *)malloc(sizeof(AVPacket) * 1);
av_init_packet(avpkt);  
avpkt->data = ct;   // ct is the array
avpkt->length =....

и расшифровать avcodec_decode_video2().

Часть кода выглядит так:

...
codec = avcodec_find_decoder(CODEC_ID_H264);
gVideoCodecCtx = avcodec_alloc_context();
gFrame = avcodec_alloc_frame();
avcodec_decode_video2(gVideoCodecCtx, gFrame, &frameFinished, packet);
...

Думаю, я правильно установил все необходимые свойства, но эта функция возвращает только -1

Я только что обнаружил, что -1 исходит от

ret = avctx->codec->decode(avctx, picture, got_picture_ptr, avpkt);

в avcodec_decode_video2();

На самом деле, мне интересно, как я могу декодировать пакеты H264 (без заголовка RTP) с помощью avcodec_decode_video2()?


Обновлено:

Хорошо, я все еще пытаюсь найти решение. То, что я делаю сейчас, это ниже

** Поток H264 в этом потоке RTP кодируется FU-A.

  1. Получить RTP-пакет

  2. Посмотрите, равен ли второй байт заголовка RTP > 0, что означает, что это первый пакет (и, возможно, за ним последует)

  3. Посмотрите, имеет ли следующий пакет RTP > 0 во втором байте, то это означает, что предыдущий кадр был полным NAL, или если это ‹ 0, пакет должен быть добавлен к предыдущему пакету.

  4. Удалите все заголовки RTP пакетов, чтобы он имел только индикатор FU | Заголовок ФУ | НАЛ

  5. Попробуйте поиграть с avcodec_decode_video2()

Но он возвращает только -1.....
Должен ли я также удалить индикатор FU и заголовок??

Любое предложение будет очень признательно


person Jun    schedule 16.02.2012    source источник


Ответы (3)


На самом деле, мне интересно, могу ли я декодировать пакеты H264 (без заголовка RTP) с помощью avcodec_decode_video2().

Вам может потребоваться предварительная обработка полезной нагрузки RTP (повторная сборка фрагментированных NALU, разделение агрегированных NALU) перед передачей блоков NAL в декодер, если вы используете режимы пакетирования, отличные от режима одиночного блока NAL. Типы блоков NAL (STAP, MTAP, FU), разрешенные в потоке, зависят от режима пакетирования. Прочтите RFC 6184 для получения дополнительной информации о режимах пакетирования.

Во-вторых, хотя я не так хорошо знаком с FFMPEG, это может быть скорее общая проблема декодирования H.264: вы всегда должны инициализировать декодер с последовательностью H.264 (SPS) и наборами параметров изображения (PPS), прежде чем вы будете может декодировать другие кадры. Вы сделали это?

person Ralf    schedule 17.02.2012
comment
Спасибо, Ральф, оказалось, что spydroid отправляет пакеты rtp в одиночном режиме nal и в режиме fu-1, поэтому я думаю, что мне нужно обрабатывать пакеты как RTP с заголовком для случая fu-1, но я понятия не имею, как декодировать RTP с помощью библиотеки ffmpeg. Я думаю, что нет функции, работающей с уровнем RTP, и поэтому я начинаю эту работу с H264 :( .. могу ли я получить какой-либо совет по этому поводу? - person Jun; 20.02.2012
comment
Если ffmpeg не работает на уровне RTP, вам придется либо написать этот код самостоятельно, прежде чем передавать его в FFMPEG (это не так уж плохо), либо использовать другую стороннюю библиотеку. Live555 (www.live555.com) будет библиотекой LGPL с открытым исходным кодом, которая, среди прочего, обрабатывает RTP, включая пакетирование полезной нагрузки H.264. - person Ralf; 20.02.2012
comment
@Ralf Я считаю, что пакетный режим с одним блоком NAL также является частью RFC6184, см. RFC в разделе 5.6. Я не уверен, почему вы говорите, что для этого не требуется заголовок RTP. Пожалуйста, поправьте меня, если я ошибаюсь. - person Krishna Oza; 07.12.2015
comment
@Krishna_Oza Спасибо, правда, я не очень хорошо это выразил. Обновленный ответ. - person Ralf; 07.12.2015

Я не думаю, что вы сможете декодировать пакеты H264 без заголовка RTP, так как в заголовки RTP встроено довольно много информации о видеопотоке. В то же время я предполагаю, что вся информация о видеопотоке может дублироваться в видеопакетах RTP. Так что это также зависит от того, как генерируется поток.

Вибгьор

person Mukesh    schedule 17.02.2012
comment
Спасибо, Vibgyor, на самом деле отправителем является spydroid с открытым исходным кодом, и его rtp-заголовок не выглядит содержащим много вещей ... он состоит из типа полезной нагрузки, порядкового номера, отметки времени, идентификатора источника синхронизации ... любой из них означает информацию о видеопотоке ?? Я так не думаю .. Я все еще работаю над этим и буду обновлять свой прогресс. - person Jun; 17.02.2012

Это мой рабочий код

bool VideoDecoder::decode(const QByteArray &encoded)
{
    AVPacket packet;
   av_new_packet(&packet, encoded.size());
   memcpy(packet.data, encoded.data(), encoded.size());
   //TODO: use AVPacket directly instead of Packet?
   //TODO: some decoders might in addition need other fields like flags&AV_PKT_FLAG_KEY

   int ret = avcodec_decode_video2(d->codec_ctx, d->frame, &d->got_frame_ptr, &packet);
   av_free_packet(&packet);

   if ((ret < 0) || (!d->got_frame_ptr))
       return false;

    d->sws_ctx = sws_getCachedContext(d->sws_ctx
        , d->codec_ctx->width, d->codec_ctx->height, d->codec_ctx->pix_fmt
        , d->width, d->height, d->pix_fmt
        , (d->width == d->codec_ctx->width && d->height == d->codec_ctx->height) ? SWS_POINT : SWS_BICUBIC
        , NULL, NULL, NULL
        );

    int v_scale_result = sws_scale(
        d->sws_ctx,
        d->frame->data,
        d->frame->linesize,
        0,
        d->codec_ctx->height,
        d->picture.data,
        d->picture.linesize
        );
    Q_UNUSED(v_scale_result);

    if (d->frame->interlaced_frame)
        avpicture_deinterlace(&d->picture, &d->picture, d->pix_fmt, d->width, d->height);
    return true;
}
person SourabhKus    schedule 28.03.2017