簡體   English   中英

ffmpeg無法解碼某些h264流

[英]ffmpeg does not decode some h264 streams

我在局域網上有一些ip攝像機。我使用live555庫接收視頻流(我以testRtspClient為基礎),並使用ffmpeg(avcodec_decode_video2)解碼幀。 一切都很好。 當我嘗試解碼來自互聯網的流時,問題開始了。

第一個問題-一些數據包丟失,因此出現缺陷。 但這不是問題。 問題-停止並開始視頻流后,必須等待約5分鍾的流,然后ffmpeg才能從同一IP攝像機解碼某些內容。 如果數據包沒有丟失,那就沒問題了。

第二個問題-有攝像頭發送分辨率為2048х1538的視頻。 這種分辨率的幀由幾個數據包發送。 live555通常將它們放在一起,但是當幀傳輸到解碼器時,解碼器返回數據包長度,但得到的幀始終為0。

這是我的一些代碼:

#define RECEIVE_BUFFER_SIZE 1000000
AVCodecContext* avCodecContext; //definition
AVFrame *frame;  //definition
...
//init code
_fReceiveBuffer = new uint8_t[RECEIVE_BUFFER_SIZE+512]; //buffer to receive frame
ZeroMemory(_fReceiveBuffer, RECEIVE_BUFFER_SIZE + 512); //zeros
_bufferSize = RECEIVE_BUFFER_SIZE * sizeof(uint8_t); //buffer size

static const  uint8_t startCode[4] = { 0x00, 0x00, 0x00, 0x01 }; //this is for 0 0 0 1
//before frame will transfer to decoder
memcpy(_fReceiveBuffer, (void*)startCode, sizeof(uint8_t)* 4);
_fReceiveBuffer += sizeof(sizeof(uint8_t)* 4);
_bufferSize -= sizeof(sizeof(uint8_t)* 4);

AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264); //find codec

avCodecContext = avcodec_alloc_context3(codec); 
avCodecContext->flags |= AV_PKT_FLAG_KEY;
avcodec_open2(avCodecContext, codec, NULL);

frame = av_frame_alloc();

//frame
void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned durationInMicroseconds) {

if (strcmp(fSubsession.codecName(), "H264") == 0)
{
    //code from onvif device manager
    static const uint8_t startCode3[] = { 0x00, 0x00, 0x01 };
    static const uint8_t startCode4[] = { 0x00, 0x00, 0x00, 0x01 };
    auto correctedFrameSize = frameSize;
    auto correctedBufferPtr = fPlObj->_fReceiveBuffer;
    if (frameSize < sizeof(startCode4) || memcmp(startCode4, correctedBufferPtr, sizeof(startCode4)) != 0){
        if (frameSize < sizeof(startCode3) || memcmp(startCode3, correctedBufferPtr, sizeof(startCode3)) != 0){
            correctedFrameSize += sizeof(uint8_t)* 4;
            correctedBufferPtr -= sizeof(uint8_t)* 4;
        }
    }

    ProcessFrame(correctedBufferPtr, correctedFrameSize, presentationTime, durationInMicroseconds);
}
continuePlaying();
}

void DummySink::ProcessFrame(unsigned char* framePtr, int frameSize, struct timeval presentationTime, unsigned duration)    {

AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.data = framePtr;
avpkt.size = frameSize;
while (avpkt.size > 0) {
    int got_frame = 0;

    int len = avcodec_decode_video2(avCodecContext, frame, &got_frame, &avpkt);
    if (len < 0) {
        //TODO: log error
        return;
    }
    else if (got_frame == 0)
    {
//I tried this code, bacause "codecs which have the AV_CODEC_CAP_DELAY capability set have a delay between input and output"
//but it didn't help
        /*AVPacket emptyPacket;
        av_init_packet(&emptyPacket);
        emptyPacket.data = NULL;
        emptyPacket.size = 0;
        emptyPacket.stream_index = avpkt.stream_index;
        len = avcodec_decode_video2(avCodecContext, frame, &got_frame, &emptyPacket);
        if ( got_frame == 1) goto next;*/
        return;
    }
next:
    //... here code for view with DirectDraw - everithing ok with it
    avpkt.size -= len;
    avpkt.data += len;
}
}

我也嘗試過將幀發送到帶有sps和pps信息的解碼器:

0 0 0 1 sps 0 0 0 1 pps 0 0 0 1 frame

但這沒有幫助。

有趣的是,avcodec_decode_video2不會返回第二個問題的幀(返回幀的所有大小),但是avCodecContext中的寬度和高度設置正確。 我不能理解為什么它不返回框架。

任何人都可以幫助解決這些問題嗎?

我通過在TCP上使用rtp而不是在udp上使用rtp解決了這些問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM