video quality patches for vlc (based on 0.9.8a)

Feature requests for VLC.
bryanair
Blank Cone
Blank Cone
Posts: 13
Joined: 03 Feb 2009 13:37

video quality patches for vlc (based on 0.9.8a)

Postby bryanair » 09 Apr 2009 01:20

Over the last several weeks I have been involved in a project ( for Airgain, Inc. ) in which we have a need to produce the highest possible quality streaming video using specific encodings and format. In the process I have discovered (and corrected) several minor problems in the vlc 0.9.8a player that contribute towards distorted or otherwise "unreliable" playback, as well as some observed problems in the live555 library with respect to the proper use of 'select'.

After applying our fixes, vlc is able to flawlessly play streaming video via RTSP [using UDP]. On a related note, we also had to fix problems in the open source streaming media server, as well as the live555 library, which made finding (and correcting) these problems all that more difficult.

FIX #1: frame buffer size [verified still exists in latest 'git' repository fetch]

In the modules/demux/live555.cpp file, function 'SessionsSetup', the track buffer is ALWAYS pre-allocated to 64k bytes [this value is actually hard-coded]. However, it appears that the intent was to determine how large the buffer SHOULD be by calculating the correct size in 'i_buffer'. The patch simply uses 'i_buffer's value in lieu of 65536, as follows:

// Airgain begin - increase video buffer to 'i_buffer' bytes (see above)
// tk->i_buffer = 65536;
// tk->p_buffer = (uint8_t *)malloc( 65536 );
tk->i_buffer = i_buffer;
tk->p_buffer = (uint8_t *)malloc( i_buffer );
// Airgain end

without the patch applied, each frame that exceeds the last allocated buffer size causes dropped packets, and corresponding video distortion [sometimes bad enough to crash the player]. Using errors [that lose data] to drive memory allocation is simply bad practice anyway, and so the intent of using 'i_buffer' rather than 65536 fixes this problem for even the highest bandwidth HD movies that we've tried so far.


Fix #2: correct I-frame timing

[NOTE: in the 'git' source tree from today I noticed some effort that may in some cases alleviate this problem, specifically Getcc and the information it collects, though it's likely the base cause of the problem goes uncorrected without the proposed patches]

This was very difficult to find. It appears that when streaming H.264 video contains B frames, if the content is 'just right' you could end up applying a B frame's timing (or even a preceding P frame's timing) to an I frame, causing 'shudders' in the playback. This is infrequent, although I was able to prove that it was actually happening through the use of debug messages.

Correcting the problem required patching two files, include/vlc_block.h and modules/packetizer/h264.c

In modules/packetizer/h264.c the function ParseNALBlock attempts to correct a problem where dts and pts are indicated as 'zero' for an I frame, by capturing the frame blocks FIRST dts and pts and applying that to everything in the frame block. Unfortunately, H.264 allows you to have multiple timings within the same block, so this method can't always work. Instead, a patch to block_ChainExtract corrects this problem by finding the first non-zero dts/pts within the same chain and using THAT instead. So, if the first entry of an I frame has a dts/pts of zero, the next entry probably won't - and so you use the NEXT entry's dts/pts value via the patch (which will be the correct value).

the function block_ChainExtract (include/vlc_block.h) is patched as follows:

static size_t block_ChainExtract( block_t *p_list, void *p_data, size_t i_max )
{
size_t i_total = 0;
uint8_t *p = (uint8_t*)p_data;
// Airgain begin
block_t *p_list0 = p_list;
// Airgain end

while( p_list && i_max )
{
size_t i_copy = __MIN( i_max, p_list->i_buffer );
memcpy( p, p_list->p_buffer, i_copy );
i_max -= i_copy;
i_total += i_copy;
p += i_copy;
// Airgain begin
if(!p_list0->i_dts && !p_list0->i_pts)
{
p_list0->i_dts = p_list->i_dts;
p_list0->i_pts = p_list->i_pts;
}
// Airgain end
p_list = p_list->p_next;
}
return i_total;
}


Then, a corresponding set of patches in modules/packetizer/h264.c un-does the workaround that uses 'i_frame_dts' and 'i_frame_pts' in lieu of the actual dts/pts as follows:

(in ParseNALBlock, near the end)

/* Append the block */
if( p_frag )
block_ChainAppend( &p_sys->p_frame, p_frag );

*pb_used_ts = false;
if( p_sys->i_frame_dts < 0 && p_sys->i_frame_pts < 0 )
{
// Airgain begin - if B frame or i_frag_pts is zero, do NOT assign frame [pd]ts !
if(i_frag_pts && p_sys->slice.i_frame_type != 8)
{
// Airgain end
p_sys->i_frame_dts = i_frag_dts;
p_sys->i_frame_pts = i_frag_pts;
*pb_used_ts = true;
// Airgain begin
}
// Airgain end
}
return p_pic;
}

(in OutputPicture, near the end)

else
{
p_pic = block_ChainGather( p_sys->p_frame );
}
// Airgain begin - do not assign i_[pd]ts from frame [pd]ts unless mine are <= 0
if(p_pic->i_dts <= 0 && p_pic->i_pts <= 0)
{
// Airgain end
p_pic->i_dts = p_sys->i_frame_dts;
p_pic->i_pts = p_sys->i_frame_pts;
// Airgain begin
}
// Airgain end
p_pic->i_length = 0; /* FIXME */
p_pic->i_flags |= p_sys->slice.i_frame_type;

p_sys->slice.i_frame_type = 0;
p_sys->p_frame = NULL;
p_sys->i_frame_dts = -1;
p_sys->i_frame_pts = -1;
p_sys->b_slice = false;

return p_pic;
}


Fix #3: (X11 only) - using XFlush + usleep to send commands to XServer and thread-switch _before_ XSync

One observation that I made regarding X11 video performance is that OCCASIONALLY you would end up with delay times around the 'XSync' call that exceeded the frame to frame timing by several times over (as long as 100msec at times). Additionally there was an accumulation of memory footprint for the X Server. It appeared as if the calls to the X Server were being made in such a way that normal background tasks were being pre-empted until "everything backed up". The problem manifested itself as infrequent "stops" and frame drops in high bandwidth video playback, and occasionally as "tears" where part of a frame was rendered on one vertical scan interval, and the rest on subsequent scan interval(s).

[I had an earlier post with respect to this patch but I'm repeating it again anyway as part of this, since it's relevant and not in the latest 'git' repository fetch]

In the file modules/video_output/x11/xcommon.c, function 'DisplayVideo', a call to XSync correctly follows all of the calls that prepare (but do not necessarily send) a set of commands for the X server. Unfortunately, the effects of making this call in this way include the occasional "garbage collection" or other 'interruptive' task that causes dropped frames to occur when they otherwise should not. The proposed well-tested patch, which attempts to work around an apparent problem in the X11 library, is as follows:

(modules/video_output/x11/xcommon.c, function DisplayVideo, near the end)

}

// Airgain begin - XFlush to send commands, usleep to force context switch.
// This is likely to help client/server interaction
XFlush( p_vout->p_sys->p_display ); // force commands to be sent
usleep(500); // then switch contexts before waiting
// Airgain end
/* Make sure the command is sent now - do NOT use XFlush !*/
XSync( p_vout->p_sys->p_display, False );

vlc_mutex_unlock( &p_vout->p_sys->lock );
}




Please implement these patches (or their equivalent functionality) at the earliest possibility. Thanks

bryanair
Blank Cone
Blank Cone
Posts: 13
Joined: 03 Feb 2009 13:37

Re: video quality patches for vlc (based on 0.9.8a)

Postby bryanair » 09 Apr 2009 01:22

there was an inadvertent "smiley" inserted into the patch code - the line should read more like

if(i_frag_pts && p_sys->slice.i_frame_type != 8 )

Jean-Baptiste Kempf
Site Administrator
Site Administrator
Posts: 37523
Joined: 22 Jul 2005 15:29
VLC version: 4.0.0-git
Operating System: Linux, Windows, Mac
Location: Cone, France
Contact:

Re: video quality patches for vlc (based on 0.9.8a)

Postby Jean-Baptiste Kempf » 09 Apr 2009 02:25

Thanks a lot for the feedback, but could you send this to vlc-devel@videolan.org mailing list, please?
Jean-Baptiste Kempf
http://www.jbkempf.com/ - http://www.jbkempf.com/blog/category/Videolan
VLC media player developer, VideoLAN President and Sites administrator
If you want an answer to your question, just be specific and precise. Don't use Private Messages.

VinX
Blank Cone
Blank Cone
Posts: 12
Joined: 14 Oct 2008 02:54

Re: video quality patches for vlc (based on 0.9.8a)

Postby VinX » 09 Apr 2009 13:55

hi,bryanair, I used your solution to patch the VLC.
But the h264 RTP stream including B frames was still "shudders"(jittery).
Thanks for your suggestion.

bryanair
Blank Cone
Blank Cone
Posts: 13
Joined: 03 Feb 2009 13:37

Re: video quality patches for vlc (based on 0.9.8a)

Postby bryanair » 09 Apr 2009 19:44

which video server were you using? We had to patch a specific open-source video server that sends inaccurate RTCP server reports every few seconds, and if you're using the same video server, that may be your problem. FYI the reason for the inaccurate server reports is that the application maintains internal frame timing at MILLISECOND resolution. I patched it with a 'hack' that re-evaluates the frame timing at MICROSECOND resolution (right before rendering) based on the RTP timestamp (which is what live555 uses when it calculates frame timing for vlc) and the 'B' frame problem went away. FYI live555 uses the RTCP server reports to re-calibrate its mapping between 'wall time' (aka 'time on the clock on the wall') and the RTP timestamps in the RTP packet headers. If the 'wall time' is incorrect for a packet, live555 will apply an incorrect adjustment to all packets following the report. If this happens on a 'B' frame, you get a B frame with an inaccurate timestamp (usually a positive value), and this causes severe 'jitter' problems. Yes, tracing this down was somewhat difficult. Still it's relevant to vlc considering the tight relationship between 'dts/pts' and the RTP frame decoding by live555.

So I guess I should summarize the bug fix in that it fixes 'tiny' jitters, which are still visible but not grotesque like the ones being caused by the streaming server's inaccurate timing.

bryanair
Blank Cone
Blank Cone
Posts: 13
Joined: 03 Feb 2009 13:37

Re: video quality patches for vlc (based on 0.9.8a) and live555

Postby bryanair » 10 Apr 2009 02:59

hi,bryanair, I used your solution to patch the VLC.
But the h264 RTP stream including B frames was still "shudders"(jittery).
Thanks for your suggestion.
There may be more than one problem, as Bob wrote in detail.

If you're running this on Linux / BSD, using live555, you will want the relevant patches to 'select' usage
that we posted today, look for "select" or "airgain" in April 2009. There are also patches for the Windows API usages, but mostly affects the rarely occuring return conditions; it was not clear whether Windows select / recvfrom behave differently and would not need the separate call to socketioctl that we added.

http://lists.live555.com/pipermail/live-devel/

Months ago we used packet capture (CACE Turbocap) and determined that streaming server was not sending us all packets, and made patches to eliminate packet loss there too. Even the very latest of the open source projects we found needed to be patched; we just recently posted to the relevant developer list.

Regards
Bryan
http://www.Airgain.com

VinX
Blank Cone
Blank Cone
Posts: 12
Joined: 14 Oct 2008 02:54

Re: video quality patches for vlc (based on 0.9.8a)

Postby VinX » 10 Apr 2009 03:54

Thanks very much for your reply.
1. video sever: I use a very simple stream sever which is made by myself. This stream sever conforms to RFC3984.
1) First, I use x264 to make 264 raw files, and produce many files according to x264 setting parameters (e.g. --bframes)..
2) Then, I use the simple stream sever made by myself to multicast video stream for h264 over RTP.
3) It just sends RTP packets(doesn't send RTCP reports), and the increment timestamp of every frame is according to 264 files's fps.
2. the vlc client(0.9.8a) receives the multicast video stream.
3. If the 264 raw files have B frames, the pictures on vlc client are very "shudders"(jittery). If the 264 raw files don't include B frames, the pictures on vlc client are OK.
4. But if I use mplayer to play these streams, no matter 264 files whether having B frames, the playback is very good.

problems:
1. what's your "specific open-source video server"?
2.In my stream sever, there is not SR, and so there is not "wall time". Does it affect vlc's presentation?
3.Does the timestamp in the RTP header affect presentation?
4.the 264 decoding order(IPBB) and presentation order(IBBP), is it the reason of jitter? If the 264 files don't have B frames, the decoding order and presentation order is "I P".

bryanair
Blank Cone
Blank Cone
Posts: 13
Joined: 03 Feb 2009 13:37

Re: video quality patches for vlc (based on 0.9.8a)

Postby bryanair » 10 Apr 2009 22:58

most likely we should take this part of the conversation off line - I'll try contacting you directly via the forum

hillbilly1980
Blank Cone
Blank Cone
Posts: 13
Joined: 14 Oct 2008 04:07
VLC version: 1.1.4
Operating System: Ubuntu
Location: Nelson, BC
Contact:

Re: video quality patches for vlc (based on 0.9.8a)

Postby hillbilly1980 » 30 Apr 2009 21:16

I'm not sure the changes in live555.cpp are necessary, i was having issues with the first frames being dropped but found this page at live555

http://www.live555.com/liveMedia/faq.html#packet-loss

A little more searching and I increased my buffers in the following sysctls. I was dropping 164 bytes above and beyond the default of 65536, hence teh 65700 below, you might want to increase that further. Since making that change i stopped getting the dropped trailling bytes error, which was leading to dropped frames and quality corruption at the beginning of my mosaic. I'm not sure if vlc polls these numbers before launching but it seems to be the case. Just food for thought.

sysctl -w net.core.wmem_max=8388608
sysctl -w net.core.rmem_default=65700
sysctl -w net.core.wmem_default=65700
sysctl -w net.ipv4.tcp_rmem='4096 87380 8388608'
sysctl -w net.ipv4.tcp_wmem='4096 65536 8388608'
sysctl -w net.ipv4.tcp_mem='8388608 8388608 8388608'

hillbilly1980
Blank Cone
Blank Cone
Posts: 13
Joined: 14 Oct 2008 04:07
VLC version: 1.1.4
Operating System: Ubuntu
Location: Nelson, BC
Contact:

Re: video quality patches for vlc (based on 0.9.8a)

Postby hillbilly1980 » 01 May 2009 13:12

I was wrong the error still existed. Testing tonight and saw it consistently, only difference was the lights where the cameras are installed, solid black picture = larger frames maybe. Regardless applied patch and it worked just fine. I'll compare the quality when the lights come back on.


Return to “VLC media player Feature Requests”

Who is online

Users browsing this forum: No registered users and 18 guests