ShixX
ShixX

Reputation: 51

Windows Media Encoder not saving MF_MT_MPEG_SEQUENCE_HEADER

I'm want to use the Win7 Media Foundation SDK to encode videoframes into H264 and then use a sinkwriter to save them as an .mp4 file. However, the sinkwriter finalization fails when I don't manually add the MF_MT_MPEG_SEQUENCE_HEADER to the output mediatype and the file is not playable.

I checked the encoder, which should add it (see H.264 Video Encoder). But it just gives the MF_E_ATTRIBUTENOTFOUND Error.

IMFMediaType * outputType;
hr = m_pEncoder->GetOutputCurrentType(0, &outputType);
UINT32 sequenceHeaderDataSize;
hr = outputType->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &sequenceHeaderDataSize);

With a MF_MT_MPEG_SEQUENCE_HEADER, which I found online (for 1080p), I was able to get a playable file. However it has still some errors in the brightness (random changes ~ every 0.5 seconds) and blocking errors.

UINT8 blob[] = {0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x2A, 0xAD, 0x84, 0x01, 0x0C, 0x20, 0x08, 0x61, 0x00, 0x43, 0x08, 0x02, 0x18, 0x40, 0x10, 0xC2, 0x00, 0x84, 0x2B, 0x50, 0x3C, 0x01, 0x13, 0xF2, 0xC2, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x79, 0x08, 0x00, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x3C, 0xB0};


//create sink attributes
IMFAttributes *  sinkAttributes = NULL;
HRESULT hr = MFCreateAttributes(&sinkAttributes, 1);
hr = sinkAttributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, true);

//create sink
IMFSinkWriter * pSinkWriter = NULL;
hr = MFCreateSinkWriterFromURL(L"output.mp4", NULL, sinkAttributes, &pSinkWriter);

// Set the output media type.
IMFMediaType * pMediaTypeOut = NULL;
CHECK_HR(MFCreateMediaType(&pMediaTypeOut));
CHECK_HR(pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
CHECK_HR(pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT));
CHECK_HR(MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT));
CHECK_HR(MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1));
CHECK_HR(pMediaTypeOut->SetBlob(MF_MT_MPEG_SEQUENCE_HEADER, blob, sizeof(blob)));
CHECK_HR(pSinkWriter->AddStream(pMediaTypeOut, &streamIndex));

// Tell the sink writer to start accepting data.
hr = pSinkWriter->BeginWriting();

This may be windows 7 related, I am not able to check on a windows 10 computer unfortunately.

The encoded frames are needed somewhere else, so I can't just skip the encoding and put my frames directly into the sink.

Upvotes: 3

Views: 325

Answers (1)

Roman Ryltsov
Roman Ryltsov

Reputation: 69632

Some encoders, like - if I recall correctly - quite popular and available on Windows 7 Intel Quick Sync, make MF_MT_MPEG_SEQUENCE_HEADER available only after your start sample processing. That is, when you manage the MFT you have to do ProcessInput, ProcessOutput, handle dynamic format change, change the media type and there in the new media type you have the sequence header. That is, you are supposed to start encoding and initialize the sink writer only when you are ready with the data received from encoder after initial input is sent there.

You have to have proper MF_MT_MPEG_SEQUENCE_HEADER and you cannot hard code random values. You can for troubleshooting purposes as you did, but those are not just some bytes for given resolution.

Note Windows 8 updates to MPEG-4 source and sink:

SPS and PPS can be extracted from input samples in MPEG-4 sink.

When SPS and PPS are not set through MF_MT_MPEG_SEQUENCE_HEADER on input media type of the MPEG-4 sink, MPEG-4 sink will try to extract SPS and PPS from input samples. MPEG-4 sink ignores any input samples until it finds the first SPS and PPS, because all input samples without SPS and PPS are not decode-able.

So indeed, things working in Windows 8 due to updates are not available in Windows 7 and you have to handle the MF_MT_MPEG_SEQUENCE_HEADER yourselves.

Upvotes: 2

Related Questions