используя FFmpeg, как декодировать пакеты H264 - PullRequest
5 голосов
/ 16 февраля 2012

Я новичок в 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, пакет должен быть добавлен к предыдущему пакету. </p>

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

  5. попробуйте воспроизвести его с помощью avcodec_decode_video2 ()

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

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

заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 17 февраля 2012

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

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

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

1 голос
/ 17 февраля 2012

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

Vibgyor

0 голосов
/ 28 марта 2017

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

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;
}
...