Hi,all, please help with rtp/H264 decode, thanks

Steam recording with RTMPDump or FFmpeg.
Post Reply
jiansu2002
Posts: 3
Joined: Wed Jun 04, 2014 2:46 am

Hi,all, please help with rtp/H264 decode, thanks

Post by jiansu2002 » Wed Jun 04, 2014 3:10 am

Hi, all,

Now I get H264 RTP packets like [SPS Slice] | [PPS Slice] |[IDR Slice 1]| [IDR Slice2] | [IDR Slice3]. Detailed in the attachment.
H264 RTP Wirshark stream.PNG
I combine the slices into a frame before put it into avcodec_decode_video2. The way I combine the slices is as so: [0001][SPS][0001][PPS][0001][IDR Slice 1][0001][IDR Slice 2][0001][IDR Slice 3].

signedrslt = avcodec_decode_video2(pContext, pFrame, &frameFinished, &packet);

But always get 0 as signedrslt = 0;frameFinished=0. Please give me a hint. thanks.

James

jiansu2002
Posts: 3
Joined: Wed Jun 04, 2014 2:46 am

Re: Hi,all, please help with rtp/H264 decode, thanks

Post by jiansu2002 » Thu Jun 05, 2014 6:05 am

Continuing with my last post.

My code as below:

void UnPackRTPIntoVideo()
{
BYTE i;
UINT8 *pBuf;
unsigned short nSize;

UINT32 dwBufSize;
UINT8 ucVideoBufPos;
T_BUFMSG tMsg;

for( i=0;i<MAX_RTPBUF_NUM;i++)
{
if(tRTPBuf.ucRTPBufFg == 1)
{
if ( tRTPBuf.tBufMsg.wMsgLen <= 12 )
{
FreeRTPBufPos(i);
}

pBuf = (unsigned char *)tRTPBuf.tBufMsg.pvReq;
nSize = tRTPBuf.tBufMsg.wMsgLen;
UINT8 *cp = (UINT8*)&m_RTP_Header ;
cp[0] = pBuf[0] ;
cp[1] = pBuf[1] ;

m_RTP_Header.seq = pBuf[2] ;
m_RTP_Header.seq <<= 8 ;
m_RTP_Header.seq |= pBuf[3] ;

m_RTP_Header.ts = pBuf[4] ;
m_RTP_Header.ts <<= 8 ;
m_RTP_Header.ts |= pBuf[5] ;
m_RTP_Header.ts <<= 8 ;
m_RTP_Header.ts |= pBuf[6] ;
m_RTP_Header.ts <<= 8 ;
m_RTP_Header.ts |= pBuf[7] ;

m_RTP_Header.ssrc = pBuf[8] ;
m_RTP_Header.ssrc <<= 8 ;
m_RTP_Header.ssrc |= pBuf[9] ;
m_RTP_Header.ssrc <<= 8 ;
m_RTP_Header.ssrc |= pBuf[10] ;
m_RTP_Header.ssrc <<= 8 ;
m_RTP_Header.ssrc |= pBuf[11] ;

UINT8 *pPayload;
DWORD PayloadSize;
UINT16 wExtlength;

if(m_RTP_Header.x == 0)
{
pPayload = pBuf + 12 ;
PayloadSize = nSize - 12 ;
}
else
{
rtp_ext_hdr_t exthdr;
memcpy((void *)&exthdr,(pBuf + 12),4);
wExtlength = exthdr.ucExtlen1 + (exthdr.ucExtlen2<<8);

pPayload = pBuf + 12 + 4 +wExtlength*4;
PayloadSize = nSize - (12 + 4 +wExtlength*4) ;
}



// Check the RTP version number (it should be 2):
if ( m_RTP_Header.v != RTP_VERSION )
{
FreeRTPBufPos(i);
}
// Check the Payload Type. strengthened this later
/*
if ( m_RTP_Header.pt != m_H264PAYLOADTYPE )
{
FreeRTPBufPos(i);
} */
/*

+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
*/

int PayloadType = pPayload[0] & 0x1f ;
int NALType = PayloadType;
if ( NALType == 28 ) // FU_A
{
if ( PayloadSize < 2 )
{
FreeRTPBufPos(i);
}

NALType = pPayload[1] & 0x1f ;
}

if ( m_ssrc != m_RTP_Header.ssrc )
{
m_ssrc = m_RTP_Header.ssrc;
SetLostPacket () ;
}

if ( NALType == 0x07 ) // SPS
{
m_bSPSFound = true ;
}

if ( !m_bSPSFound ) //need to be strengthened
{
FreeRTPBufPos(i);
}

if ( NALType == 0x07 || NALType == 0x08 ) // SPS PPS
{
m_wSeq = m_RTP_Header.seq ;
m_bPrevFrameEnd = true ;

pPayload -= 4 ;
*((DWORD*)(pPayload)) = 0x01000000 ;

m_bWaitKeyFrame = true;

/*put the pPayload into the video buf*/
if(1)
{
dwBufSize = PayloadSize + 4;
tMsg.wMsgLen = dwBufSize;
tMsg.pvReq = malloc(dwBufSize);
if (tMsg.pvReq == NULL)
{
//osal_dbg_print(OSAL_DBG_PRN_LEVEL_2,"[OSAL]:OsNetDrvRecvPacket: osal_msg_malloc_buf return NULL\n");
FreeRTPBufPos(i);
continue;
}
memcpy((UINT8*)(tMsg.pvReq),pPayload,dwBufSize);

FindEmptyVideoBufPos(&ucVideoBufPos);
tVideoBuf[ucVideoBufPos].ucVideoType = VIDEOTYPE_H264;
tVideoBuf[ucVideoBufPos].ucNALType = NALType;
memcpy((void *)&tVideoBuf[ucVideoBufPos].tBufMsg,(void *)&tMsg,sizeof(T_BUFMSG));

FreeRTPBufPos(i);
continue;

}

if ( m_bWaitKeyFrame )
{
if ( m_RTP_Header.m ) // frame end
{
m_bPrevFrameEnd = true ;
if ( !m_bAssemblingFrame )
{
m_wSeq = m_RTP_Header.seq;
FreeRTPBufPos(i);
continue;
}
}

if ( !m_bPrevFrameEnd )
{
m_wSeq = m_RTP_Header.seq ;
FreeRTPBufPos(i);
continue;
}
else
{
if ( NALType != 0x05 ) // KEY FRAME
{
m_wSeq = m_RTP_Header.seq ;
m_bPrevFrameEnd = false ;
FreeRTPBufPos(i);
continue;
}
}
}
if ( m_RTP_Header.seq != (WORD)( m_wSeq + 1 ) )//lost packet
{
m_wSeq = m_RTP_Header.seq ;
SetLostPacket () ;
FreeRTPBufPos(i);
continue;
}
else
{
m_wSeq = m_RTP_Header.seq ;
m_bAssemblingFrame = true ;
if ( PayloadType != 28 ) // whole NAL
{
*((DWORD*)(m_pStart)) = 0x01000000 ;
m_pStart += 4 ;
m_dwSize += 4 ;
}
else // FU_A
{
if ( pPayload[1] & 0x80 ) // FU_A start
{
*((DWORD*)(m_pStart)) = 0x01000000 ;
m_pStart += 4 ;
m_dwSize += 4 ;

pPayload[1] = ( pPayload[0] & 0xE0 ) | NALType ;

pPayload += 1 ;
PayloadSize -= 1 ;
}
else
{
pPayload += 2 ;
PayloadSize -= 2 ;
}
}

if ( m_pStart + PayloadSize < m_pEnd )
{
CopyMemory ( m_pStart, pPayload, PayloadSize ) ;
m_dwSize += PayloadSize ;
m_pStart += PayloadSize ;
}
else // memory overflow
{
SetLostPacket();
FreeRTPBufPos(i);
continue;
}

if ( m_RTP_Header.m ) // frame end
{
//*outSize = m_dwSize ;

if ( NALType == 0x05 ) // KEY FRAME
{
m_bWaitKeyFrame = false;
}

/*put the payload into the video buf*/
if(1)
{
dwBufSize = m_dwSize;
tMsg.wMsgLen = dwBufSize;
tMsg.pvReq = malloc(dwBufSize);
if (tMsg.pvReq == NULL)
{
FreeRTPBufPos(i);
continue;
}
memcpy((UINT8*)(tMsg.pvReq),m_pBuf,dwBufSize);

FindEmptyVideoBufPos(&ucVideoBufPos);
tVideoBuf[ucVideoBufPos].ucVideoType = VIDEOTYPE_H264;
tVideoBuf[ucVideoBufPos].ucNALType = NALType;
memcpy((void *)&tVideoBuf[ucVideoBufPos].tBufMsg,(void *)&tMsg,sizeof(T_BUFMSG));

FreeRTPBufPos(i);

m_pStart = m_pBuf ;
m_dwSize = 0 ;

continue;

}
}
else
{
FreeRTPBufPos(i);
continue;
}
}
}
}

return;
}

void PlayVideoInit()
{
pCodec = NULL;
pContext = NULL;
pFrame = NULL;

m_pVideoDecoFrame = new UINT8[MAX_VIDEO_FRAME_LEN];

memset((void *)&packet,0,sizeof(AVPacket));
arghwtf = (char *)malloc(INBUF_SIZE);

pCodec = avcodec_find_decoder(CODEC_ID_H264);
if(pCodec == NULL)
{
//goto stream_decode_finish;
}

pContext = avcodec_alloc_context3(pCodec);
if(pContext == NULL)
{
//goto stream_decode_finish;
}

//init the context
avcodec_get_context_defaults3(pContext,pCodec);
pContext->codec_type = AVMEDIA_TYPE_VIDEO;
pContext->pix_fmt = PIX_FMT_YUV420P;


if(avcodec_open2(pContext, pCodec, NULL) < 0)
{
//goto stream_decode_finish;
}

pFrame = av_frame_alloc();
if(pFrame == NULL)
{
//goto stream_decode_finish;
}
pFrameYUVorRGB = av_frame_alloc();
if( pFrameYUVorRGB == NULL )
{
//return -1;
}

unsigned long cacheSize = (1024 << 10);
pSrcData = (unsigned char *)malloc(cacheSize);
if(pSrcData == NULL)
{
//goto stream_decode_finish;
}
memset(pSrcData, 0, cacheSize);
ucCurStatus = PLAYVIDEO_WAITSPS;

sdlWindow = SDL_CreateWindowFrom((const void *)thisPanel->Handle);

if( !sdlWindow ) {
//fprintf(stderr, "SDL: could not set video mode - exiting\n");
return;
}

sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);
return;
}

void PlayVideo()
{
UINT8 nextNalPos = 0;

UINT8 *ptemp = NULL;
UINT16 wtemplen;
int width,height;
ptemp = new UINT8[100] ;
int signedrslt;
int frameFinished;

int ret = GetNextVideoPos(pSrcData,&nextNalPos);
while(ret != 0xFF)
{
switch(ucCurStatus)
{
case PLAYVIDEO_WAITSPS:
if(ret == 1)
{
//get the width and length
wtemplen = tVideoBuf[nextNalPos].tBufMsg.wMsgLen;
if((wtemplen <=100) && (wtemplen>0))
{
if(1)
{
memcpy(ptemp, tVideoBuf[nextNalPos].tBufMsg.pvReq,wtemplen);
getResolution(ptemp,(UINT8)wtemplen,&width,&height);
pContext->width = (UINT16)width;
pContext->height = (UINT16)height;

ResizeImg(pContext->width,pContext->height,
thisPanel->Width,thisPanel->Height,
&w, &h );

sws_ctx = sws_getContext(pContext->width,pContext->height,pContext->pix_fmt,//PIX_FMT_YUV420P
w,h,PIX_FMT_YUV420P, //PIX_FMT_YUV420P,
SWS_POINT, //SWS_BILINEAR,
NULL,NULL,NULL);

numBytes = avpicture_get_size(PIX_FMT_YUV420P,w,h);
if(pdecodeRsltBuf)
av_free(pdecodeRsltBuf);
pdecodeRsltBuf = (UINT8 *)av_malloc( numBytes*sizeof(UINT8));
avpicture_fill((AVPicture *)pFrameYUVorRGB,pdecodeRsltBuf,PIX_FMT_YUV420P, w,h);

if(sdlTexture)
SDL_DestroyTexture(sdlTexture);
sdlTexture = SDL_CreateTexture(sdlRenderer,SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,pContext->width,pContext->height);

sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = pContext->width;
sdlRect.h = pContext->height;

SDL_RenderClear( sdlRenderer );
SDL_RenderCopy( sdlRenderer, sdlTexture, &sdlRect, &sdlRect );
SDL_RenderPresent( sdlRenderer );

}

memcpy(m_pVideoDecoFrame,tVideoBuf[nextNalPos].tBufMsg.pvReq,wtemplen);
wVideoDecoLen = wtemplen;
wVideoDecoCurPos = wtemplen;

packet.data = m_pVideoDecoFrame;
packet.size = wVideoDecoLen;
avcodec_get_frame_defaults(pFrame);
signedrslt = avcodec_decode_video2(pContext, pFrame, &frameFinished, &packet);

FreeVideoBufPos(nextNalPos);

ucCurStatus = PLAYVIDEO_WAITPPS;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
else
{
FreeVideoBufPos(nextNalPos);
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
}
else
{
FreeVideoBufPos(nextNalPos);
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
break;

case PLAYVIDEO_WAITPPS:
if(ret == 2)
{
wtemplen = tVideoBuf[nextNalPos].tBufMsg.wMsgLen;
memcpy(m_pVideoDecoFrame+wVideoDecoCurPos,tVideoBuf[nextNalPos].tBufMsg.pvReq,wtemplen);
wVideoDecoLen = wVideoDecoLen + wtemplen;
wVideoDecoCurPos = wVideoDecoCurPos + wtemplen;

packet.data = m_pVideoDecoFrame;
packet.size = wVideoDecoLen;
avcodec_get_frame_defaults(pFrame);
signedrslt = avcodec_decode_video2(pContext, pFrame, &frameFinished, &packet);

FreeVideoBufPos(nextNalPos);

ucCurStatus = PLAYVIDEO_WAITIDR;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
else
{
//wrong packet, need to do clean work
FreeVideoBufPos(nextNalPos);
ucCurStatus = PLAYVIDEO_WAITSPS;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
break;

case PLAYVIDEO_WAITIDR:
if(ret == 1 || ret == 2)
{
wVideoDecoLen = 0;
wVideoDecoCurPos = 0;
ucCurStatus = PLAYVIDEO_WAITSPS;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
else
{
wtemplen = tVideoBuf[nextNalPos].tBufMsg.wMsgLen;

memcpy(m_pVideoDecoFrame+wVideoDecoCurPos,tVideoBuf[nextNalPos].tBufMsg.pvReq,wtemplen);
wVideoDecoLen = wVideoDecoLen + wtemplen;
wVideoDecoCurPos = wVideoDecoLen + wtemplen;

memcpy(m_pVideoDecoFrame + wVideoDecoCurPos, m_pFrameEnd, 5);
wVideoDecoLen = wVideoDecoLen + 5;
wVideoDecoCurPos = wVideoDecoLen + 5;

packet.data = m_pVideoDecoFrame;
packet.size = wVideoDecoLen;
avcodec_get_frame_defaults(pFrame);
signedrslt = avcodec_decode_video2(pContext, pFrame, &frameFinished, &packet);

FreeVideoBufPos(nextNalPos);
ucCurStatus = PLAYVIDEO_GO;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
break;

case PLAYVIDEO_GO:
if(ret == 1 || ret == 2)
{
wVideoDecoLen = 0;
wVideoDecoCurPos = 0;
ucCurStatus = PLAYVIDEO_WAITSPS;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
else
{
//start decode and playwork
wtemplen = tVideoBuf[nextNalPos].tBufMsg.wMsgLen;

memcpy(m_pVideoDecoFrame+wVideoDecoCurPos,tVideoBuf[nextNalPos].tBufMsg.pvReq,wtemplen);
wVideoDecoLen = wVideoDecoLen + wtemplen;

//memcpy(m_pVideoDecoFrame,tVideoBuf[nextNalPos].tBufMsg.pvReq,wtemplen);
//wVideoDecoLen = wtemplen;

//av_init_packet(&packet);
packet.data = m_pVideoDecoFrame;
packet.size = wVideoDecoLen;


avcodec_get_frame_defaults(pFrame);
signedrslt = avcodec_decode_video2(pContext, pFrame, &frameFinished, &packet);
// Did we get a video frame?
if( frameFinished )
{
sws_scale(sws_ctx,(uint8_t const * const *)pFrame->data,pFrame->linesize,
0,pContext->height,pFrameYUVorRGB->data,pFrameYUVorRGB->linesize);

SDL_UpdateTexture(sdlTexture,&sdlRect,pFrameYUVorRGB->data[0],pFrameYUVorRGB->linesize[0]);

SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer,sdlTexture,&sdlRect,&sdlRect);
SDL_RenderPresent(sdlRenderer);
}

wVideoDecoLen = 0;
wVideoDecoCurPos = 0;

FreeVideoBufPos(nextNalPos);
ucCurStatus = PLAYVIDEO_GO;
ret = GetNextVideoPos(pSrcData,&nextNalPos);
}
break;

default:
//
break;
}
}
return;
}
Last edited by jiansu2002 on Sun Jun 08, 2014 7:12 am, edited 1 time in total.

rogerdpack
Posts: 1878
Joined: Fri Aug 05, 2011 9:56 pm

Re: Hi,all, please help with rtp/H264 decode, thanks

Post by rogerdpack » Sun Jun 08, 2014 5:09 am

so did it work?

jiansu2002
Posts: 3
Joined: Wed Jun 04, 2014 2:46 am

Re: Hi,all, please help with rtp/H264 decode, thanks

Post by jiansu2002 » Sun Jun 08, 2014 7:10 am

hi rogerdpack,

Sorry, it doesn't work. avcodec_decode_video2 always returns 0.

James

rogerdpack
Posts: 1878
Joined: Fri Aug 05, 2011 9:56 pm

Re: Hi,all, please help with rtp/H264 decode, thanks

Post by rogerdpack » Mon Jun 09, 2014 6:37 am

maybe ask on the libav-user mailing list?

Post Reply