MftH264Decoder::DecoderOutputState MftH264Decoder::GetOutput() {
CComPtr<IMFSample> output_sample;
if (!use_dxva_) {
// If DXVA is enabled, the decoder will allocate the sample for us.
output_sample.Attach(CreateEmptySampleWithBuffer(out_buffer_size_));
if (output_sample == NULL) {
cout<< "GetSample: failed to create empty output sample";
return kNoMemory;
}
}
MFT_OUTPUT_DATA_BUFFER output_data_buffer;
HRESULT hr;
DWORD status;
for (;;) {
output_data_buffer.dwStreamID = 0;
output_data_buffer.pSample = output_sample;
output_data_buffer.dwStatus = 0;
output_data_buffer.pEvents = NULL;
hr = decoder_->ProcessOutput(0, // No flags
1, // # of out streams to pull from
&output_data_buffer,
&status);
IMFCollection* events = output_data_buffer.pEvents;
if (events != NULL) {
cout<< "Got events from ProcessOuput, but discarding";
events->Release();
}
if (FAILED(hr)) {
cout<< "ProcessOutput failed with status " << std::hex << hr
<< ", meaning..." << ProcessOutputStatusToCString(hr);
if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
if (!SetDecoderOutputMediaType(output_format_)) {
cout<< "Failed to reset output type";
return kResetOutputStreamFailed;
} else {
cout<< "Reset output type done";
continue;
}
} else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
// If we have read everything then we should've sent a drain message
// to the MFT. If the drain message is sent but it doesn't give out
// anymore output then we know the decoder has processed everything.
if (drain_message_sent_) {
cout<< "Drain message was already sent + no output => done";
return kNoMoreOutput;
} else {
if (!ReadAndProcessInput()) {
cout<< "Failed to read/process input. Sending drain message";
if (!SendDrainMessage()) {
cout<< "Failed to send drain message";
return kNoMoreOutput;
}
}
continue;
}
} else {
return kUnspecifiedError;
}
}
The above function is my implementation of H264 Decoder. The input samples are read from the H264 dump file as an elementary stream. Initially i am trying to passing only the first frame which s of size 1043 and passing it to decoder.
bool MftH264Decoder::ReadAndProcessInput() {FILE *pFile;
int bytes_read =0;
int bytes_remaining = 1043;
int read =0;
pFile = fopen ("Bourne.264","rb");
if (pFile == NULL)
{
cout<<"File Error";
}
char *in_buffer = NULL;
in_buffer = (char*) malloc (sizeof(char)*2000);
if(in_buffer == NULL)
{
cout<<"Memory error";
}
bytes_read=fread (in_buffer,1,1043,pFile);
fclose(pFile);
return SendInput((unsigned char*)in_buffer,1043,0,0);
}
bool MftH264Decoder::SendInput(unsigned char* data, int size, long long timestamp,
long long duration) {
/*if(initialized_)
{
return false;
}*/
// CHECK(data != NULL);
// CHECK_GT(size, 0);
if (drain_message_sent_) {
cout<< "Drain message was already sent, but trying to send more "
"input to decoder";
return false;
}
CComPtr<IMFSample> sample;
sample.Attach(CreateInputSample(data, size, timestamp, duration,
in_buffer_size_));
if (sample == NULL) {
cout<< "Failed to convert input stream to sample";
return false;
}
HRESULT hr = decoder_->ProcessInput(0, sample, 0);
if (FAILED(hr)) {
cout<< "Failed to ProcessInput, hr = " << std::hex << hr;
return false;
}
frames_read_++;
return true;
}
The processOutput function always returns MF_E_TRANSFORM_NEED_MORE_INPUT as a result it keeps on reading the first frame from the buffer.
Is this the correct way of calling Process Input and Process output functions?