Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

h264 decoder exceptions

maxrd2
Beginner
518 Views
Hello,

I'm using IPP 6.1.5.054. I've took h264 decoder from IPP examples and integrated it into my project.
H264 encoder works fine and produces correct output (have tested it with h264 reference decoder).

The problem is when I pass that stream to h264 decoder. After 3-4 frames are feeded to it, it starts throwing exceptions and decompressed video gets corrupted.

Here is the part of code where I'm initializing decoder and decoding frames:

[cpp]H264Source::H264Source()
{
	if(!ipp_init_done) {
		ipp_init_done = true;
		ippStaticInit();
	}
	last_buffer = NULL;
	wnd = NULL;
	graph = NULL;
	renderer = NULL;
	source = NULL;
	active = false;
	decoder_initialized = false;
	own_last_buffer = false;
	video_vflip = false;
	
	decoder = new UMC::H264VideoDecoder();
	params = new UMC::H264VideoDecoderParams();
	
	decoder_mutex = CreateMutex(NULL, FALSE, NULL);
	last_buffer_mutex = CreateMutex(NULL, FALSE, NULL);
}

/*virtual*/ bool
H264Source::source_frame_output(char **buf, int *len)
{
	if(!active)
		return true;

	VIDEOINFO *vi = (VIDEOINFO *)media_type.pbFormat;
	BITMAPINFOHEADER *bi = &vi->bmiHeader;

	char *fbuf = NULL;
	int flen = 0;

	// returns the exact video buffer as created by IPP H.264 Encoder
	if(!buffer_get(&fbuf, &flen))
		return false;

	if(flen == 0)
		return true;

	UMC::MediaData src;
	src.Reset();
	src.SetTime(frame_counter + 1 / (10000000 / vi->AvgTimePerFrame));
	src.SetBufferPointer((Ipp8u *)fbuf, flen);
	src.SetDataSize(flen);

	if(decoder_initialized == false) {
		WaitForSingleObject(decoder_mutex, INFINITE);
		int st = UMC::UMC_ERR_FAILED;
		UMC::H264VideoDecoderParams par;
		if((fbuf[4] & 0x1f) == 7) {
			params->numThreads = 1;
			params->info.stream_type = UMC::H264_VIDEO;
			params->lFlags = 0;
			params->m_pData = &src;
			
			st = decoder->Initparams;
			if(st == UMC::UMC_OK) {
				st = decoder->GetInfo(&par);
				if(st != UMC::UMC_OK) {
					decoder->Close();
					log_printf(LOG_INFO, "H264Source::source_frame_output(%08x) init decoder video params failed: %d", decoder, st);
				}
			} else {
				log_printf(LOG_INFO, "H264Source::source_frame_output(%08x) init decoder video failed: %d", decoder, st);
			}
		} else {
			log_printf(LOG_INFO, "H264Source::source_frame_output(%08x) init decoder video: skipping non SPS frame", decoder);
		}
		if(st == UMC::UMC_OK) {
			decoder_initialized = true;
			log_printf(LOG_INFO, "H264Source::source_frame_output(%08x) init decoder video %dx%d", decoder, par.info.clip_info.width, par.info.clip_info.height);
		}
		ReleaseMutex(decoder_mutex);
		
		src.Close();
		buffer_free(fbuf);
		return true;
	}

	UMC::VideoData dst;
	dst.Init(vid_info.bmiHeader.biWidth, vid_info.bmiHeader.biHeight, 1, 8);
	dst.SetColorFormat(UMC::RGB24);
	dst.Reset();
	dst.SetBufferPointer((Ipp8u *)*buf, *len);

	WaitForSingleObject(decoder_mutex, INFINITE);

	int st = decoder->GetFrame(&src, &dst);

	ReleaseMutex(decoder_mutex);
	
	src.Close();
	buffer_free(fbuf);
	
	if(st != UMC::UMC_OK && st != UMC::UMC_ERR_NOT_ENOUGH_DATA) {
		*len = 0;
		log_printf(LOG_DEBUG, "H264Source decoder %08x finished with %d", decoder, st);
		return false;
	}
	
	size_t dlen = dst.GetDataSize();
//
// ***** If I uncomment this code decoder usually goes on for about an hour before it starts giving exceptions *****
//
//	if(dlen == 0) {
//		// try to force frame output
//		WaitForSingleObject(decoder_mutex, INFINITE);
//		st = decoder->GetFrame(NULL, &dst);
//		ReleaseMutex(decoder_mutex);
//		if(st != UMC::UMC_OK && st != UMC::UMC_ERR_NOT_ENOUGH_DATA) {
//			log_printf(LOG_DEBUG, "H264Source decoder %08x finished with %d", decoder, st);
//			return false;
//		}
//		dlen = dst.GetDataSize();
//	}

	if(dlen >= *len) {
		frame_counter++;
		*len = dlen;
	} else {
		*len = 0;
	}
	dst.Close();

	return true;
}
[/cpp]

There is piece of code that is commented out which forces frame output from decoder (usually it buffers them before output) and if I uncomment that, decoder goes on for an hour before throwing exceptions.

I've tried to debug exception and have found this:
The exception is thrown because ippiDecodeExpGolombOne_H264_1u32s() is trying to parse bad golomb value, which is called from some macroblock decoding/parsing method, and have noticed that pointer that is passed to ippiDecodeExpGolombOne_H264_1u32s() is 4 bytes before end of macroblock buffer, and I suppose ippiDecodeExpGolombOne_H264_1u32s() overflows because it's reading non golomb data.

I've thought that stream gets corrupted because it doesn't makes a copy of buffer that is passed in, so I've tried omiting calling Close() on src and free() it's buffer, but except memory leaks it didn't change a thing.

Can you please help me?

thanks
Max
0 Kudos
7 Replies
maxrd2
Beginner
518 Views
is there anyone who can help me with this please?
0 Kudos
Naveen_G_Intel
Employee
518 Views
Hi Max,
Can you tell me which version of IPP you are using?

Regards,
Naveen Gv
0 Kudos
maxrd2
Beginner
518 Views
Hi Naveen, sorry for my slow reply.. Version I'm using is 6.1.5.054 But same is happening with 6.1.2 best regards Max
0 Kudos
CraigC
Beginner
518 Views
Was there a resolution here?
I appear to be getting the same problem trying to decode a H264 stream from the Polycom phone.
0 Kudos
CraigC
Beginner
518 Views
Please, any help would be appricated here...
I am using IPP version 6.1.137.763, the specific problem is ocurring in umc_h264_bitstream_inlines.h, line 495.
[bash]inline
Ipp32s H264Bitstream::GetVLCElement(bool bIsSigned)
{
    Ipp32s sval = 0;

    IppStatus ippRes = ippiDecodeExpGolombOne_H264_1u32s(&m_pbs, &m_bitOffset, &sval, bIsSigned);

    if (ippStsNoErr > ippRes)
        throw h264_exception(UMC_ERR_INVALID_STREAM);

    return sval;

}[/bash]
ippResis -5.
I can supply wireshark traces of the stream from the phone etc. if need be.
0 Kudos
CraigC
Beginner
518 Views
Is there any reason for the lack of response here, have I asked the question in a confusing or vauge manner?
0 Kudos
Pavel_V_Intel
Employee
518 Views
We had changed behaviour of this function in IPP7.0.2 to skip very long codes without error. So update should help you with this problem.
0 Kudos
Reply