<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2900.2769" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2>Hi Ross, hi all,</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>for a MPEG-4 video stream, generated with ffmpeg, 
&nbsp;we found out that the timestamps were not generated always correcctly. The 
timestamps are not increasing monoton. The video also showed flickering and 
short breaks.</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Without having fully understood the parsing of the 
MPEG-4 stream, I found out that the problem disappeares when the variable 
fPrevNewTotalTicks is reseted when a new time code is parsed from the file. (see 
code below)</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Perhaps somebody better understands the code and 
can verify that the change makes sense.&nbsp;</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Best regards,</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial size=2>Bernhard</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT>&nbsp;</DIV>
<DIV><FONT face=Arial 
size=2>------------------------------------------------------</FONT></DIV>
<DIV><FONT face="Courier New" size=2>MPEG4VideoStreamFramer.cpp</FONT></DIV>
<DIV><FONT face="Courier New" size=2>&nbsp;</FONT></DIV>
<DIV><FONT face="Courier New" size=2>...</FONT></DIV>
<DIV><FONT face="Courier New" size=2>unsigned 
MPEG4VideoStreamParser::parseGroupOfVideoObjectPlane() {<BR>#ifdef 
DEBUG<BR>&nbsp; fprintf(stderr, "parsing 
GroupOfVideoObjectPlane\n");<BR>#endif<BR>&nbsp; // Note that we've already read 
the GROUP_VOP_START_CODE<BR>&nbsp; 
save4Bytes(GROUP_VOP_START_CODE);</FONT></DIV>
<DIV><FONT face="Courier New" size=2></FONT>&nbsp;</DIV>
<DIV><FONT face="Courier New" size=2>&nbsp; // Next, extract the (18-bit) time 
code from the next 3 bytes:<BR>&nbsp; u_int8_t next3Bytes[3];<BR>&nbsp; 
getBytes(next3Bytes, 3);<BR>&nbsp; 
saveByte(next3Bytes[0]);saveByte(next3Bytes[1]);saveByte(next3Bytes[2]);<BR>&nbsp; 
unsigned time_code<BR>&nbsp;&nbsp;&nbsp; = 
(next3Bytes[0]&lt;&lt;10)|(next3Bytes[1]&lt;&lt;2)|(next3Bytes[2]&gt;&gt;6);<BR>&nbsp; 
unsigned time_code_hours&nbsp;&nbsp;&nbsp; = 
(time_code&amp;0x0003E000)&gt;&gt;13;<BR>&nbsp; unsigned time_code_minutes&nbsp; 
= (time_code&amp;0x00001F80)&gt;&gt;7;<BR>#if defined(DEBUG) || 
defined(DEBUG_TIMESTAMPS)<BR>&nbsp; Boolean 
marker_bit&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 
(time_code&amp;0x00000040) != 0;<BR>#endif<BR>&nbsp; unsigned 
time_code_seconds&nbsp; = (time_code&amp;0x0000003F);<BR>#if defined(DEBUG) || 
defined(DEBUG_TIMESTAMPS)<BR>&nbsp; fprintf(stderr, "time_code: 0x%05x, hours 
%d, minutes %d, marker_bit %d, seconds %d\n", time_code, time_code_hours, 
time_code_minutes, marker_bit, time_code_seconds);<BR>#endif</FONT></DIV>
<DIV><FONT face="Courier New" size=2></FONT>&nbsp;</DIV>
<DIV><FONT face="Courier New" size=2>&nbsp; // Now, copy all bytes that we see, 
up until we reach a VOP_START_CODE:<BR>&nbsp; u_int32_t next4Bytes = 
get4Bytes();<BR>&nbsp; while (next4Bytes != VOP_START_CODE) 
{<BR>&nbsp;&nbsp;&nbsp; saveToNextCode(next4Bytes);<BR>&nbsp; }</FONT></DIV>
<DIV><FONT face="Courier New" size=2></FONT>&nbsp;</DIV>
<DIV><FONT face="Courier New" size=2>&nbsp; // Compute this frame's presentation 
time:<BR>&nbsp; 
usingSource()-&gt;computePresentationTime(fTotalTicksSinceLastTimeCode);</FONT></DIV>
<DIV><FONT face="Courier New" size=2></FONT>&nbsp;</DIV>
<DIV><FONT face="Courier New" size=2>&nbsp; // Record the time code:<BR>&nbsp; 
usingSource()-&gt;setTimeCode(time_code_hours, 
time_code_minutes,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
time_code_seconds, 0, 0);<BR>&nbsp;&nbsp;&nbsp; // Note: Because the GOV header 
can appear anywhere (not just at a 1s point), we<BR>&nbsp;&nbsp;&nbsp; // don't 
pass "fTotalTicksSinceLastTimeCode" as the "picturesSinceLastGOP" 
parameter.<BR>&nbsp; fSecondsSinceLastTimeCode = 0;</FONT></DIV><FONT 
face="Courier New" size=2>
<DIV><BR>&nbsp; fPrevNewTotalTicks = 0;&nbsp;&nbsp;&nbsp; 
//&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; bf 051031, try to 
eliminate some errors with wrong time stamps<BR></DIV>
<DIV>&nbsp; if (fixed_vop_rate) fTotalTicksSinceLastTimeCode = 0;</FONT></DIV>
<DIV><FONT face="Courier New" size=2></FONT>&nbsp;</DIV>
<DIV><FONT face="Courier New" size=2>&nbsp; 
setParseState(PARSING_VIDEO_OBJECT_PLANE);</FONT></DIV>
<DIV><FONT face="Courier New" size=2></FONT>&nbsp;</DIV>
<DIV><FONT face="Courier New" size=2>&nbsp; return 
curFrameSize();<BR>}</FONT></DIV>
<DIV><FONT face="Courier New" size=2>...</FONT></DIV></BODY></HTML>