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);已经设置了播放声音时间,它与视频保持一致的,前面的上下文也看了多次,没有发现什么异样,不会为什么后半段声音有问题。 若有知情者欢迎留言说明原因。