Long latency, upstream and downstream

Source: Internet
Author: User

How can we delay your program by 1 ms, 2 Ms ......

I used the timer () function for a long time when I used vbprogramming. However, after careful analysis, we will find that the timer () function has a very low precision, and the precision can only reach a dozen milliseconds. That is to say, if your intention is to delay 1 millisecond, in fact, the latency is several dozen milliseconds. What is the evidence? How can we see it? The following simple vbprogram will illustrate the problem:

Option explicit

Private sub commandementclick ()

Dim I as long, J as long

For I = 0 to 1000000

For J = 0-999

Delay (1) 'If delay (1) is really delayed for one millisecond, it takes only one second to execute 1000 cycles.

Next J


Label1.caption = label1.caption + 1

Doevents

Next I

End sub

'Msec millisecond
Private sub delay (byval msec as long)

Dim TMR as long

TMr = timer * 1000

Do

Doevents

Loop until timer * 1000-TMR> msec

End sub

The Code does not need to be explained too much. If delay (1) is really delayed for one millisecond, it takes only one second to execute 1000 cycles. The value of the label control is increased every second. Run the command (without pseudocode, compile and execute it again). The number takes about 10 seconds to jump. In fact, this method is enough for scenarios with low precision requirements. I used to write a jsgplayer to play tunnel ad files in a custom format. This method is used for inter-frame latency, because it is a simple player that does not require high precision, although the frame rate may be somewhat different, the effect is indeed acceptable.

Now, because we need 264 decoding, and RTP transmission, inter-frame latency, data package splitting, and group packages must all be precisely synchronized, we cannot accept this precision. If the delay is not accurate, it will cause congestion, packet loss (not timely reception), and Slow playback (this problem cannot be fooled, the standard video files used for testing have a lot of Uniform Motion lenses, which can be easily seen if there is pause or frame jump during playback. If you are playing a normal movie, you may be able to fool the past :-) how can we achieve accurate millisecond-level latency? I have embarked on a long journey.

Can I try other methods? The API functions gettickcount () and Microsoft's multimedia clock (functions in mmsystem. Lib) have been tested and found that gettickcount () and VB are of the same type, with an accuracy of more than 10 milliseconds. Microsoft's multimedia clock accuracy is somewhat higher, but it is far from milliseconds, I also heard that the accuracy of the multimedia clock has something to do with your computer hardware and the version of Windows and DirectX you have installed. For example, it may be highly accurate on your computer, on my computer, it is not necessarily highly accurate. This feature is enough to make it abandoned. I don't want to work hard to complete the program and put it on another computer, but it cannot run normally.

After hard searching on the internet, I finally found a method that can achieve latency of 1 Millisecond (theoretically, this method can achieve latency of nanoseconds, but it does not actually make much sense, when you call a delayed function, the overhead of the function call takes dozens of nanoseconds ). The Code has been sorted out and has been written into a dynamic link library by VC, which can be called by VB and VC. Of course, it is better to rewrite it into a class to be used in VC.

The Linked Library has three functions: 1. Use the getfreq () function to obtain the CPU clock speed; 2. Use the asmdelay () function to obtain the precise latency; 3. Use stopwatchbegin () function to enable stopwatch (stopwatch is a word, stopwatchend () to close the stopwatch, and return the total number of milliseconds from enabling the stopwatch to closing the stopwatch. This function is applicable to code performance statistics.

 

The Code is as follows :----------------------------------------------------------------------------------------------------------------------------

// Highdelay. cpp: defines the initialization routines for the DLL.
//

//
// High-precision timer code.
// Because the precision is too high, it is only suitable for latency less than 1 second (that is, 1000 ms) (more than one second, the unsigned long variable will overflow ).
// For latency greater than 1 second, use multiple asmdelay combinations;
// Delay principle, through the CPU instruction period register, CPU clock speed, through calculation, delay a certain instruction period. Theoretical Source: network.
// Author :.
//

# Include "stdafx. H"
# Include "highdelay. H"

# Ifdef _ debug
# Define new debug_new
# UNDEF this_file
Static char this_file [] = _ file __;
# Endif

//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this dll which
// Call into MFC must have the afx_manage_state macro
// Added at the very beginning of the function.
//
// For example:
//
// Extern "C" bool Pascal export exportedfunction ()
//{
// Afx_manage_state (afxgetstaticmodulestate ());
/// Normal function body here
//}
//
// It is very important that this macro appear in each
// Function, prior to any callinto MFC. This means that
// It must appear as the first statement within
// Function, even before any object variable declarations
// As their constructors may generate callinto the MFC
// DLL.
//
// Please see MFC technical notes 33 and 58 for additional
// Details.
//

//////////////////////////////////////// /////////////////////////////////////
// Chighdelayapp

Begin_message_map (chighdelayapp, cwinapp)
// {Afx_msg_map (chighdelayapp)
// Note-The classwizard will add and remove mapping macros here.
// Do not edit what you see in these blocks of generated code!
//} Afx_msg_map
End_message_map ()

//////////////////////////////////////// /////////////////////////////////////
// Chighdelayapp Construction

Chighdelayapp: chighdelayapp ()
{
// Todo: Add construction code here,
// Place all significant initialization in initinstance
}

//////////////////////////////////////// /////////////////////////////////////
// The one and only chighdelayapp object

Chighdelayapp theapp;

// The following is the custom code: //////////////////////////////////////// /////////////////

// Module-level variable CPU frequency, MHz, which must be converted to Hz in actual use;
Unsigned int m_freq = 0;
_ Int64 m_stopwatchstarttimestamp; // specifies the CPU timestamp when the stopwatch is enabled.

// Obtain the internal function of CPU frequency // MHz
Int getfrequency (void)
{
Large_integer currticks, tickscount;
_ Int64 istartcounter, istopcounter;

DWORD dwoldprocessp = getpriorityclass (getcurrentprocess ());
DWORD dwoldthreadp = getthreadpriority (getcurrentthread ());

Setpriorityclass (getcurrentprocess (), realtime_priority_class );
Setthreadpriority (getcurrentthread (), thread_priority_time_critical );

Queryperformancefrequency (& tickscount );
Queryperformancecounter (& currticks );

Tickscount. quadpart/= 16;
Tickscount. quadpart + = currticks. quadpart;

_ ASM rdtsc
_ ASM mov dword ptr istartcounter, eax
_ ASM mov dword ptr (istartcounter + 4), EDX

While (currticks. quadpart <tickscount. quadpart)
Queryperformancecounter (& currticks );

_ ASM rdtsc
_ ASM mov dword ptr istopcounter, eax
_ ASM mov dword ptr (istopcounter + 4), EDX

Setthreadpriority (getcurrentthread (), dwoldthreadp );
Setpriorityclass (getcurrentprocess (), dwoldprocessp );

Return (INT) (istopcounter-istartcounter)/62500 );
}

Unsigned _ int64 getcyclecount () // read the instruction period register of the CPU
{
_ ASM rdtsc
}

// For external APIs, see. export in the def file //////////////////////////////////// /////////////////

// Initialize the delayed Connection Library. To use the delay function correctly, you must call this function before. We recommend that you call this operation once during program initialization,
// And only one call is required. The execution of this function takes several milliseconds.
Void _ stdcall initasmdelay ()
{
M_freq = getfrequency ();
}

// Obtain the CPU clock speed through external interfaces;
Int _ stdcall getfreq ()
{If (0 = m_freq)
Return m_freq = getfrequency ();
Else
Return m_freq;
}

// High-precision latency function; msec in milliseconds;
Void _ stdcall asmdelay (unsigned long msec)
{
// Convert the number of milliseconds to the number of clock periods
Unsigned long msectocycle = (m_freq * 1000) * msec;
// Record the current clock cycle
Unsigned long TMR = (unsigned long) getcyclecount ();
// Delay until the number of clock periods meets the predefined Number of milliseconds;
While (unsigned long) getcyclecount ()-TMR <msectocycle)
{
}
}

// Stopwatch function, used to calculate how long the code has been executed;
// Enable stopwatch
Void _ stdcall stopwatchbegin ()
{
M_stopwatchstarttimestamp = getcyclecount ();
}
// Close the stopwatch and return the length of milliseconds from enabling the stopwatch to closing the stopwatch;
Long _ stdcall stopwatchend ()
{
_ Int64 timestampdiff = getcyclecount ()-m_stopwatchstarttimestamp;
Return timestampdiff/(m_freq * 1000 );
}

Certificate --------------------------------------------------------------------------------------------------------------------------------------------

The latency principle of the asmdelay () function is very simple, that is, proportional. The CPU clock speed is defined as the number of instruction cycles executed by the CPU in one second (1000 milliseconds. Assuming that the CPU clock speed is a Hz, how many instruction cycles do we need to wait for if we want to delay B Ms? Assume there are X instruction cycles. This is a proportional formula:

A/1000 = x/B

Obtain x = (A * B)/1000

Because the unit of m_freq variable in our Linked Library is MHz, It is Hz to multiply the value by 1000.

Therefore, in the asmdelay () function, you need to calculate the number of clock cycles to wait based on the number of milliseconds to be delayed. Use the following code:
Unsigned long msectocycle = (m_freq * 1000000 * msec)/1000;

After being simplified, it becomes the Code:
Unsigned long msectocycle = (m_freq * 1000) * msec;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.