mediasinkencoder样例,是用来生成rmvb文件的,其核心函数是CMediaSinkEncoderApp::EncodeSamples
HX_RESULT CMediaSinkEncoderApp::EncodeSamples()
{
HX_RESULT res = HXR_OK;
// Create media sample allocator
IHXTSampleAllocator* pAllocator = NULL;
res = m_pFactory->CreateInstance(IID_IHXTSampleAllocator, (IUnknown**)&pAllocator);
// simulation: one pass each second
UINT32 z=0;
for (z=0; z < 30 && SUCCEEDED(res); z ++)
{
// Encode an event sample
if (m_bEncodeEvents && SUCCEEDED(res))
{
// Send URL event sample
if ( z == 1000)
{
// Create event sample -- note that event sample comes from class factory
IHXTEventSample* pEventSample = NULL;
res = m_pFactory->CreateInstance(IID_IHXTEventSample, (IUnknown**)&pEventSample);
// Set target URL
if (SUCCEEDED(res))
res = pEventSample->SetAction(HXEventMediaSample_URL, "http://www.real.com ", NULL);
// Set start/finish time
if (SUCCEEDED(res))
res = pEventSample->SetTime(0, 6000);
// Encode sample
if (SUCCEEDED(res))
res = m_pEventPin->EncodeSample( pEventSample );
HX_RELEASE(pEventSample);
printf( "Sent URL Event/n" );
}
//Send a custom event sample
else if ( z == 500 )
{
IHXTEventSample* pEventSample = NULL;
IHXBuffer* pBuffer = NULL;
IHXValues* pValues = NULL;
if (SUCCEEDED(res))
res = m_pFactory->CreateInstance(IID_IHXTEventSample, (IUnknown**)&pEventSample);
if (SUCCEEDED(res))
res = m_pFactory->CreateInstance(CLSID_IHXValues, (IUnknown**)&pValues);
if (SUCCEEDED(res))
res = m_pFactory->CreateInstance(CLSID_IHXBuffer, (IUnknown**)&pBuffer);
if (SUCCEEDED(res))
{ // load up a IHXValues with name/value pairs to encode
pValues->SetPropertyULONG32("myulong32prop", 200);
pBuffer->Set((BYTE *)"my dog spot", 12);
pValues->SetPropertyCString("mystringprop", pBuffer);
}
if (SUCCEEDED(res))
res=pEventSample->SetAction(HXEventMediaSample_Custom, "mycustomevent", pValues);
if (SUCCEEDED(res))
res=pEventSample->SetTime( 5000, 15000);
if (SUCCEEDED(res))
res = m_pEventPin->EncodeSample( pEventSample );
HX_RELEASE(pBuffer);
HX_RELEASE(pValues);
HX_RELEASE(pEventSample);
printf( "Sent Custom Event/n" );
}
}
// Encode on second's worth of audio.
// Note that in practice it is a better idea to alternate between passing audio and video
// samples so that one doesn't get too far ahead of the other in terms of sample
// start times. Doing otherwise (say passing 5 seconds worth of audio at a time followed by 5 seconds worth
// of video) may result in higher than expected memory consumption.
if (m_bEncodeAudio && SUCCEEDED(res))
{
// Get media sample -- sample: 1 channel, 16 bits/sample, 44.1 khz
// Note that the the size of the buffer being allocated should exactly match the size
// of the audio chunk (do not allocate a larger buffer). Since audio start/end timestamps only
// have millisecond resolution, some portions of the Producer SDK determine the audio chunk size
// based on the buffer size, not the start/end timestamps.
IHXTMediaSample* pMediaSample=NULL;
res = pAllocator->GetMediaSampleOfSize(44100*sizeof(UINT16), &pMediaSample);
if (SUCCEEDED(res))
{
// Get the sample data buffer -- note use of GetDataStartForWriting instead of
// GetDataStartForReading since the buffer is being written to
UINT16 *y=(UINT16*)pMediaSample->GetDataStartForWriting();
float fifth = 3.0f/2.0f ;
float minthird = 6.0f/5.0f ;
float f0 = 440.0f ; // Hz
float pi = 3.1415926535f;
// Construct a minor chord
for (int i = 0 ; i < 44100 ; i++)
{
float x = (float) (2*pi*i/44100.0 * f0);
y[i] = (UINT16)(32000 * (1.0/3.0) * (sin(x) + sin(minthird*x)+ sin(fifth*x)));
}
}
// Set time
if (SUCCEEDED(res))
res = pMediaSample->SetTime(z*1000, (z+1)*1000);
// Encode sample
// Note: Do NOT reuse (read from or write to the data buffer) the media sample after passing it
// to the input pin. The media sample is not automatically memcpy'ed, and some other object may
// have a refcount on it and modify the buffer on another thread. Just release the media
// sample and get another one from the allocator.
if (SUCCEEDED(res))
res = m_pAudioPin->EncodeSample( pMediaSample );
printf("Sent audio sample time: %d/n", z*1000);
HX_RELEASE(pMediaSample);
}
// Encode one seconds worth of video frames
// Note that in practice it is a better idea to alternate between passing audio and video
// samples so that one doesn't get too far ahead of the other in terms of sample
// start times. Doing otherwise (say passing 5 seconds worth of audio at a time followed by 5 seconds worth
// of video) may result in higher than expected memory consumption.
if (m_bEncodeVideo && SUCCEEDED(res))
{
for (UINT32 ulFrameCount=1; ulFrameCount < 30; ulFrameCount++)
{
// Get media sample -- kulVideoWidth x kulVideoHeight x HXT_VIDEO_FORMAT_BGRA32_INVERTED
IHXTMediaSample* pMediaSample=NULL;
res = pAllocator->GetMediaSampleOfSize( kulVideoWidth * kulVideoHeight * sizeof(UINT32), &pMediaSample);
// Create green/blue colored scrolling frame
if (SUCCEEDED(res))
{
// Get the sample data buffer -- note use of GetDataStartForWriting instead of
// GetDataStartForReading since the buffer is being written to
UINT32* pSampleBuffer = (UINT32*)pMediaSample->GetDataStartForWriting();
for ( int i = 0; i < kulVideoHeight; i++ )
{
static UINT32 ulColorBand = 0;
ulColorBand++;
for( int j =0; j < kulVideoWidth; j++ )
{
*(pSampleBuffer+(i*kulVideoWidth)+j) = 0x0000FF00 + ulColorBand;
}
}
}
// Set start/end time
if (SUCCEEDED(res))
res = pMediaSample->SetTime(z*1000 + ulFrameCount * 33, z*1000 + ulFrameCount * 33 + 10);
// Encode sample
// Note: Do NOT reuse (read from or write to the data buffer) the media sample after passing it
// to the input pin. The media sample is not automatically memcpy'ed, and some other object may
// have a refcount on it and modify the buffer on another thread. Just release the media
// sample and get another one from the allocator.
if (SUCCEEDED(res))
res = m_pVideoPin->EncodeSample(pMediaSample);
printf("Sent video sample time: %lu/n", z*1000 + ulFrameCount * 33);
HX_RELEASE(pMediaSample);
}
}
//if (m_bEncodeAudio && SUCCEEDED(res))
//{
// // Get media sample -- sample: 1 channel, 16 bits/sample, 44.1 khz
// // Note that the the size of the buffer being allocated should exactly match the size
// // of the audio chunk (do not allocate a larger buffer). Since audio start/end timestamps only
// // have millisecond resolution, some portions of the Producer SDK determine the audio chunk size
// // based on the buffer size, not the start/end timestamps.
// IHXTMediaSample* pMediaSample=NULL;
// res = pAllocator->GetMediaSampleOfSize(44100*sizeof(UINT16), &pMediaSample);
// if (SUCCEEDED(res))
// {
// // Get the sample data buffer -- note use of GetDataStartForWriting instead of
// // GetDataStartForReading since the buffer is being written to
// UINT16 *y=(UINT16*)pMediaSample->GetDataStartForWriting();
// float fifth = 3.0f/2.0f ;
// float minthird = 6.0f/5.0f ;
// float f0 = 440.0f ; // Hz
// float pi = 3.1415926535f;
// // Construct a minor chord
// for (int i = 0 ; i < 44100 ; i++)
// {
// float x = (float) (2*pi*i/44100.0 * f0);
// y[i] = (UINT16)(24000 * (1.0/3.0) * (sin(x) + sin(minthird*x)+ sin(fifth*x)));
// }
// }
// // Set time
// if (SUCCEEDED(res))
// res = pMediaSample->SetTime(z*1000, (z+1)*1000);
// // Encode sample
// // Note: Do NOT reuse (read from or write to the data buffer) the media sample after passing it
// // to the input pin. The media sample is not automatically memcpy'ed, and some other object may
// // have a refcount on it and modify the buffer on another thread. Just release the media
// // sample and get another one from the allocator.
// if (SUCCEEDED(res))
// res = m_pAudioPin->EncodeSample( pMediaSample );
// printf("Sent audio sample time: %d/n", z*1000);
// HX_RELEASE(pMediaSample);
//}
}
// Signal that all video samples have been sent
if (m_bEncodeVideo && SUCCEEDED(res))
{
// Create media sample
IHXTMediaSample* pMediaSample = NULL;
res = pAllocator->GetMediaSampleOfSize(0, &pMediaSample);
// Mark the sample with ENDOFSTREAM flag
if (SUCCEEDED(res))
res = pMediaSample->SetSampleFlags(HXT_SAMPLE_ENDOFSTREAM);
// Set time
if (SUCCEEDED(res))
res = pMediaSample->SetTime((z+1)*1000, (z+1)*1000);
// Encode sample
if (SUCCEEDED(res))
res = m_pVideoPin->EncodeSample(pMediaSample);
HX_RELEASE(pMediaSample);
}
// Signal that all audio samples have been sent
if (m_bEncodeAudio && SUCCEEDED(res))
{
// Create media sample
IHXTMediaSample* pMediaSample = NULL;
res = pAllocator->GetMediaSampleOfSize(0, &pMediaSample);
// Mark the sample with ENDOFSTREAM flag
if (SUCCEEDED(res))
res = pMediaSample->SetSampleFlags(HXT_SAMPLE_ENDOFSTREAM);
// Set time
if (SUCCEEDED(res))
res = pMediaSample->SetTime((z+1)*1000, (z+1)*1000);
// Encode sample
if (SUCCEEDED(res))
res = m_pAudioPin->EncodeSample(pMediaSample);
HX_RELEASE(pMediaSample);
}
// Signal that all event samples have been sent
if (m_bEncodeEvents && SUCCEEDED(res))
{
// Create event sample
IHXTEventSample* pEventSample = NULL;
res = m_pFactory->CreateInstance(IID_IHXTEventSample, (IUnknown**)&pEventSample);
// Mark the sample with ENDOFSTREAM flag
if (SUCCEEDED(res))
res = pEventSample->SetSampleFlags(HXT_SAMPLE_ENDOFSTREAM);
// Set time
if (SUCCEEDED(res))
res = pEventSample->SetTime(6001, 6001);
// Encode sample
if (SUCCEEDED(res))
res = m_pEventPin->EncodeSample(pEventSample);
HX_RELEASE(pEventSample);
}
HX_RELEASE(pAllocator);
return res;
}
无论是否打开:m_bEncodeTwoPass,声音只有前半段才有,若把声音采样部分再追加到视频采样后面,这样才正常为,不知为什么?
音频中res = pMediaSample->SetTime(z*1000, (z+1)*1000);已经设置了播放声音时间,它与视频保持一致的,前面的上下文也看了多次,没有发现什么异样,不会为什么后半段声音有问题。
若有知情者欢迎留言说明原因。