|
|
|
date: Mon, 7 Apr 2008 16:48:00 -0700,
group: microsoft.public.windowsmedia.sdk
back
What are the birfields required for 16bpp samples?
I am trying to creata an ASF file holding a VC-1 compressed video stream,
using a sequence of uncompressed video as the samples. The samples are 8 bit
SD video captured with an AJA frame grabber card, or UYVY in the vernacular
of the Windows Media Format. The issue I am having is that every other call
to IWMWriter::WriteSample() fails with a return code of NS_E_INVALID_DATA.
One area I suspect is a problem is the so-called "bit fields" that are said
to be required for 16bpp uncompressed samples ( 2nd paragraph in the remards
seciton on the topic of "WMVIDEOINFOHEADER" in the Windows Media Format 11
SDK ). In the description below, as part of step 10 I could allocate this
bit field and fill it with something - but I am not sure what to do here?
I am using the Windows Media Format 11 SDK for the first time and suspect I
am making an obvious blunder some where but have not been able to uncover it.
What I am doing (with error checking eliminated):
1) I used the applicaton GenProfile.exe to create a profile (and also
the
Windows Media Profile Editor to review and modify).
Video Size is 720x508
CBR 770 Kbps
I have tried with and without interlace processing with no effect
(The actual video is interlaced)
2) Create the Writer Object and get an interface
hr = WMCreateWriter( NULL, &m_pWriter );
hr = m_pWriter->QueryInterface( IID_IWMWriterAdvanced, ( void** )
&m_pWriterAdvanced );
3) Open the profile, read it in, set it equal to a WCHAR string
char * prof_768 = "VS_CBR768-100-kf8.prx";
char * prof_file = prof_768_prog;
FILE* pfid = fopen( prof_file, "r" );
fseek(pfid, 0, SEEK_END);
long nbytes = ftell(pfid);
rewind( pfid );
char * pProfileString = (char*)malloc( sizeof(char) * nbytes );
size_t nread = fread( pProfileString, sizeof(char), nbytes, pfid );
WCHAR* pwProfString = (WCHAR*) pProfileString;
4) Create the profile Manager
IWMProfileManager* pProfMgr = NULL;
hr = WMCreateProfileManager( &pProfMgr );
5) Load profile into the profile Manager
IWMProfile *pProfile = NULL;
hr = pProfMgr->LoadProfileByData( pwProfString, &pProfile );
6) Get a StreamConfig interface
IWMStreamConfig *pStreamConfig = 0;
hr = pProfile->GetStreamByNumber( 1, &pStreamConfig ); // assuming we only
have one stream in the profile
7) Associate this profile with the Writer
hr = m_pWriter->SetProfile( pProfile );
8) Get the Stream Connection by Name and get the input to the writer that
has the same name
( this uses the function FindInputByConnection() which is a
slight modification of the function GetNamesForInputs() listed
in Step 2: of WMF 11 SDK topic: "To Enumerate Input Formats" )
hr = pStreamConfig->GetConnectionName( pwcStreamConnName, &numChar );
hr = FindInputByConnection( m_pWriter, pwcStreamConnName,
&dwWriterInputForStream );
9) Find the desired format from all supported formats on this input
-> I want packed YUV data in the UYVY byte order --> UYVY
Use the function FindInputFormat() which is part of help topic "To
Enumerate Input Formats"
IWMInputMediaProps *piwmInputMediaProps = NULL;
hr = FindInputFormat( m_pWriter, dwWriterInputForStream,
WMMEDIASUBTYPE_UYVY, &piwmInputMediaProps);
10) Assign the format to the input
hr = piwmInputMediaProps->GetMediaType( NULL, &cbSize );
int bitfieldsize = 2; // ??? how big and what to do??
WM_MEDIA_TYPE* pType = (WM_MEDIA_TYPE*) new BYTE[cbSize + bitFieldSize];
hr = piwmInputMediaProps->GetMediaType( pType, &cbSize );
pType->cbFormat = cbSize + bitFieldSize;
WMVIDEOINFOHEADER* pVidHdr = (WMVIDEOINFOHEADER*) pType->pbFormat;
BITMAPINFOHEADER* pBMHdr = &(pVidHdr->bmiHeader);
char* pBitField = ((char*)pType->pbFormat) + sizeof(WMVIDEOINFOHEADER) ;
FillMemory( pBitField, bitFieldSize, 0xff );
hr = piwmInputMediaProps->SetMediaType( pType );
hr = m_pWriter->SetInputProps( dwWriterInputForStream, piwmInputMediaProps);
11) Add a file sink for the Writer object
hr = m_pWriter->SetOutputFilename( pwcFN );
12) start adding samples...
hr = m_pWriter->BeginWriting();
INSSBuffer* pSampBuf = NULL;
INSSBuffer3 *pSampBuf3 = NULL;
BYTE* pSampBufData = NULL;
for( )
{
// allocate a INSSBuffer
hr = m_pWriter->AllocateSample( FrameSize, &pSampBuf );
// get a pointer to the data
hr = pSampBuf->GetBufferAndLength( &pSampBufData, &buflen );
// copy uncompressed video data into the buffer
m_VideoEngineFile.ReadFrame(0, &fr_time, pSampBufData );
// set buffer length
pSampBuf->SetLength( buflen );
// Set sample time
QWORD sampTime = (QWORD) (1e7 * (iSample * 1.0/29.97) + .5);
// Set up the sample flags
if( iSample == 0 )
{
sample_flags = WM_SF_CLEANPOINT | WM_SF_DISCONTINUITY | WM_SF_DATALOSS;
}
else
{
sample_flags = NULL;
}
// Finally - write the sample
hr = m_pWriter->WriteSample( dwWriterInputForStream, sampTime,
sample_flags ,pSampBuf ); // fails on about every other sample with a Sample
Is Not Valid
// release buffer
SAFE_RELEASE( pSampBuf );
SAFE_RELEASE( pSampBuf3 );
}
13) End writing and close file
m_pWriter->EndWriting();
date: Mon, 7 Apr 2008 16:48:00 -0700
author: RandPendleton
Re: What are the birfields required for 16bpp samples?
From: "RandPendleton"
> One area I suspect is a problem is the so-called "bit
> fields" that are said to be required for 16bpp
> uncompressed samples ( 2nd paragraph in the remards
> seciton on the topic of "WMVIDEOINFOHEADER" in the
> Windows Media Format 11 SDK ). In the description below,
> as part of step 10 I could allocate this bit field and
> fill it with something - but I am not sure what to do
> here?
That applies to biCompression == BI_BITFIELDS, which is RGB,
not to YUV formats.
http://msdn2.microsoft.com/en-us/library/ms532290(VS.85).aspx
http://msdn2.microsoft.com/en-us/library/ms779712(VS.85).aspx
http://msdn2.microsoft.com/en-us/library/ms787838(VS.85).aspx
http://msdn2.microsoft.com/en-us/library/ms788178(VS.85).aspx
http://msdn2.microsoft.com/en-us/library/ms788140(VS.85).aspx
http://msdn2.microsoft.com/en-us/library/ms787796(VS.85).aspx
Read all of them, even if they seem to repeat themselves.
> I am using the Windows Media Format 11 SDK for the first
> time and suspect I am making an obvious blunder some
> where but have not been able to uncover it.
I don't think the profile or the input format is your
problem, since you should otherwise be getting a failure
when you set those.
> // get a pointer to the data
> hr = pSampBuf->GetBufferAndLength( &pSampBufData, &buflen
> );
>
> // copy uncompressed video data into the buffer
> m_VideoEngineFile.ReadFrame(0, &fr_time, pSampBufData );
>
> // set buffer length
> pSampBuf->SetLength( buflen );
buflen is either 0 or MaxLength, which >= FrameSize. You
should set it to the actual used frame buffer size
(FrameSize?) otherwise, with fixed-size frames like YUV, the
write will fail.
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
date: Tue, 8 Apr 2008 01:23:46 -0400
author: Alessandro Angeli
|
|