⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audioparsebuffer.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }

    DWORD buffer_size = _p_current_buffer->StreamHeader->FrameExtent;

    //complete the buffer if it is full
    _p_current_buffer->StreamHeader->DataUsed = buffer_size;
    _p_pin->onBufferComplete();
    
    _channel1_samples_in_buffer = 0;
    _channel2_samples_in_buffer = 0;
    _p_current_buffer = NULL;
}
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
AudioIISBuffer::AudioIISBuffer():
_p_pin(NULL),
_remain_in_buffer(0),
_p_current_buffer(NULL),
_fail_count(0),
_p_partial_buffer(NULL),
_bytes_in_partial_buffer(0)
{
    KeInitializeMutex(&_mutex, 0);
}


/////////////////////////////////////////////////////////////////////////////////////////
VOID AudioIISBuffer::setPin(BasePin* p_pin)
{
    KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );

    _p_pin = p_pin;
    _remain_in_buffer= 0;
    _p_current_buffer = NULL;
    _p_partial_buffer = NULL;
    _bytes_in_partial_buffer = 0;

    KeReleaseMutex(&_mutex, FALSE);
}


/////////////////////////////////////////////////////////////////////////////////////////
VOID AudioIISBuffer::releasePin()
{
    KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );

    _p_pin = NULL;  
 
    _remain_in_buffer= 0;
    _p_current_buffer = NULL;
    _p_partial_buffer = NULL;
    _bytes_in_partial_buffer = 0;

    KeReleaseMutex(&_mutex, FALSE);
}


/////////////////////////////////////////////////////////////////////////////////////////
//
// NOTE: The format of the audio data in the buffer is as follows:
//
//       Mako supports up to 4 channels of audio output at a time.  If a channel is
// present in the current audio buffer, then a bit will be set in the data_id2 byte.
// Each channel will have 8 bytes of data in the buffer, or 4 2-byte samples.  The
// samples themselves are byte swapped, so we must byte swap each WORD, (not each DWORD).
// Of the channels that are present in the buffer, they will be in the order of 
// Channel A, Channel B, Channel C, Channel D, with only channels that are present 
// having data.
//
// We only use channels A and B, (referred to below as 1 and 2).  If A and B are both present
// the data from A is at offset 0 and the data from B is at offset 8.  If A alone is present,
// the data is at offset 0.  If B alone is present, the data is at offset 0.  Any other 
// channels that may be present are ignored.     
//

DWORD AudioIISBuffer::parseBuffer(PBYTE p_data, DWORD data_count)
{
   
   
    KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL );	
    
    DWORD copy_length = 0;
     
    //If we don't have a pin, just return the number of bytes we would have used.
    if(!_p_pin)
    {    	  
        KeReleaseMutex(&_mutex, FALSE);
        return 0;
    }   

    //Get a buffer to copy the data into
    if(!_p_current_buffer)
    {    	 
        _p_current_buffer = _p_pin->getNextBuffer();
    }
 
    if(!_p_current_buffer)
    {
    	sleep(40);  /// wait for pin buffer, unit: ms
	    _fail_count++;
	    if(_fail_count == 10)
	    {
		    KeReleaseMutex(&_mutex, FALSE);
		    return 0xffffffff;  //error
	    }
	
        KeReleaseMutex(&_mutex, FALSE);

        //No available buffer, nothing to do
        return 0;
    }
	DWORD buffer_size = _p_current_buffer->StreamHeader->FrameExtent;
     
    PBYTE p_out_buffer = (PBYTE)_p_current_buffer->StreamHeader->Data;
	 
    if(_remain_in_buffer != 0)  //continue to complete the last copy
    {
    	copy_length = _remain_in_buffer;
    	RtlCopyMemory(p_out_buffer, p_data, copy_length);
	    completeCurrentBuffer();
	    return copy_length;
	
    }

  
   // const DWORD MAX_CHANNEL_SAMPLES_IN_BUFFER = buffer_size / 4;
    if (data_count < buffer_size )
    {
    	_remain_in_buffer = buffer_size - data_count;
	    copy_length = data_count; 		
    }
    else
	{
        copy_length = buffer_size;
    }

//////////////////////////////////////////////////////////
    RtlCopyMemory(p_out_buffer, p_data, copy_length);
//////////////////////////////////////////////////////////
    if(_remain_in_buffer == 0)
    {
        completeCurrentBuffer();
    }

    KeReleaseMutex(&_mutex, FALSE);
    return copy_length;
}


/////////////////////////////////////////////////////////////////////////////////////////
VOID AudioIISBuffer::completeCurrentBuffer()
{
   
    if(!_p_current_buffer)
    {
        return;
    }

    DWORD buffer_size = _p_current_buffer->StreamHeader->FrameExtent;

    //complete the buffer if it is full
    _p_current_buffer->StreamHeader->DataUsed = buffer_size;
    _p_pin->onBufferComplete();

    _remain_in_buffer = 0;    

    _p_current_buffer = NULL;
    _fail_count = 0;
}

VOID AudioIISBuffer::completeBuffers(PBYTE p_data, DWORD data_count)
{
    if(!_p_pin || !data_count)
    {
        return;
    }

    PBYTE p_audio_buffer = p_data;
    DWORD bytes_left = data_count;
    

    //First try to complete a partial audio buffer if there is one left over
    if(_p_partial_buffer)
    {
        PKSSTREAM_HEADER p_stream_header = _p_partial_buffer->StreamHeader;

        DWORD bytes_left_in_buffer = 
            p_stream_header->FrameExtent - _bytes_in_partial_buffer;  

///////////////////////////////////////////////////////////////	  
        if(bytes_left < bytes_left_in_buffer)
        {
           RtlCopyMemory(
                (PBYTE)p_stream_header->Data + _bytes_in_partial_buffer,
                  p_audio_buffer,
                  bytes_left);
	       _bytes_in_partial_buffer += bytes_left;

	       return;  // continue to copy buffer to pin_buffer
        }
	    else
	  	{
            RtlCopyMemory(
                (PBYTE)p_stream_header->Data + _bytes_in_partial_buffer,
                  p_audio_buffer,
                  bytes_left_in_buffer);
        }

        bytes_left -= bytes_left_in_buffer;
        p_audio_buffer += bytes_left_in_buffer;
        p_stream_header->DataUsed = p_stream_header->FrameExtent;
        _p_pin->onBufferComplete();

        _p_partial_buffer = NULL;
    }

    //Now fill any other buffers that we have enough data for.
    while(bytes_left)
    {
        PKSSTREAM_POINTER p_next_buffer = _p_pin->getNextBuffer();
        if(!p_next_buffer)
        {
             break;
        }

        PKSSTREAM_HEADER p_stream_header = p_next_buffer->StreamHeader;
        DWORD bytes_to_copy = p_stream_header->FrameExtent;
	 
        if(bytes_to_copy > bytes_left)
        {
            bytes_to_copy = bytes_left;
        }

        RtlCopyMemory(
            (PBYTE)p_stream_header->Data, 
            p_audio_buffer,
            bytes_to_copy);

        if(bytes_to_copy == p_stream_header->FrameExtent)
        {
            p_stream_header->DataUsed = p_stream_header->FrameExtent;
            _p_pin->onBufferComplete();
        }
        else
        {
            //If there wasn't enough data to fill the buffer, 
            // save it in the partial buffer
            _p_partial_buffer = p_next_buffer;
            _bytes_in_partial_buffer = bytes_to_copy;
            break;
        }

        p_audio_buffer += bytes_to_copy;
        bytes_left -= bytes_to_copy;
    }

}


VOID AudioIISBuffer::sleep(LONG time)
{
    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    LARGE_INTEGER wait_time;

    wait_time.LowPart = -(time*10000);
    wait_time.HighPart = -1;

    KeDelayExecutionThread(
        KernelMode,
        FALSE,
        &wait_time);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -