2012-02-16 156 views
5

我是新來FFmpeg努力解碼H264數據包,它可以作爲uint8_t數組獲取。使用FFmpeg,如何解碼H264數據包

多次調查後,我覺得應該可以只是把數組就像一個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從

漚未來= avctx-> codec->解碼(avctx,圖片,got_picture_ptr,avpkt);

在avcodec_decode_video2

();

其實,我想知道是,如果我可以解碼ħ avcodec_decode_video2()包含264個數據包(無RTP頭)。

感謝您的幫助提前。


///////////添加

OK,我仍然試圖找到一個解決方案。我現在正在做的是以下

**在這個RTP流H264流被編碼FU-A

  1. 收到一個RTP包

  2. 看,如果第二個字節RTP頭部大於0,這意味着它是第一個數據包(可能會被跟蹤)

  3. 查看下一個RTP數據包是否在其第二個字節處也> 0,則表示前一幀是完整的NAL或如果這是< 0,那麼數據包應附加到前一個數據包。

  4. 刪除數據包的所有RTP頭,使其只有FU指標| FU header | NAL

  5. 嘗試avcodec_decode_video2()

玩它,但它只有返回-1 .....我應該刪除FU指標和標題太?

任何建議將不勝感激

在此先感謝。

回答

1

我不認爲你將能夠解碼沒有RTP頭的H264包,因爲相當多的視頻流信息被嵌入到RTP頭中。同時,我猜測有可能所有的視頻流信息都可以在RTP視頻數據包中複製。所以它也取決於流如何生成。

VIBGYOR

+0

感謝VIBGYOR,實際發送者是spydroid開源和RTP報頭看起來並不包含很多東西..它是由有效載荷類型,序列號,時間戳,同步源標識符..其中任何一個意味着視頻流信息?我不這麼認爲......我仍在努力,並會更新我的進展。 – Jun 2012-02-17 05:38:17

5

其實,我想知道是,如果我能解碼H264包(不含RTP頭)由avcodec_decode_video2()。

您可能需要預先處理RTP有效載荷(一個或多個)將NAL單元到解碼器如果使用比單NAL單元模式中的其它分組模式之前(重新組裝零散的NALU,分割聚合的NALU)。流中允許的NAL單元類型(STAP,MTAP,FU)取決於分組模式。有關打包模式的更多信息,請閱讀RFC 6184。其次,雖然我不熟悉FFMPEG,但可能更多的是一般的H.264解碼問題:您必須始終使用H.264序列(SPS)和圖像參數集(PPS)初始化解碼器,在你將能夠解碼其他幀之前。你做到了嗎?

+0

感謝Ralf,事實證明,在單一nal模式和fu-1模式下,子程序發送rtp pakcets,所以我想我需要將包作爲RTP使用頭部處理fu-1的情況,但不知道如何使用ffmpeg庫解碼RTP 。我認爲沒有與RTP級別一起工作的功能,這就是爲什麼我開始這項工作與H264 :(..我可以得到任何意見嗎? – Jun 2012-02-20 02:32:21

+0

如果ffmpeg不起作用的RTP層,你將不得不在將它傳遞給FFMPEG之前自己編寫代碼(這並不壞)或使用另一個第三方庫。Live555(www.live555.com)將是一個開放源代碼LGPL庫,可處理RTP,包括H.264有效負載特定的打包等等。 – Ralf 2012-02-20 05:56:48

+0

@Ralf我相信Single NAL單元數據包模式也是RFC6184的一部分,請參考第5.6節的RFC。我不確定你爲什麼說它不需要RTP頭。我錯了。 – 2015-12-07 12:09:18

0

這是我工作的代碼

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