[英]Problem to Decode H264 video over RTP with ffmpeg (libavcodec)
[英]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.