Media Foundation: TimeStamp первого кадра неправильно устанавливается на 0. Вместо этого ему присваивается значение 0,33C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Media Foundation: TimeStamp первого кадра неправильно устанавливается на 0. Вместо этого ему присваивается значение 0,33

Сообщение Anonymous »

Я пытаюсь прочитать два кадра (по отдельности хранящиеся в двоичных файлахframe1.bin иframe2.bin) и создать видеофайл mp4 с именем «sample.mp4». Временная метка начинается с 0,0333 (по-видимому, это значение длительности кадра), а не с 0. Я не могу найти причину этого.

Код: Выделить всё

#define MFWRITER_RETURN_ON_ERROR(A) if( !(A) ) { return false; }
#define MFWRITER_RETURN_HRESULT_ON_ERROR(A) if( FAILED(A) ) {return A; }

const double HUNDRED_NANOSECONDS = 10000000.0;

class MFInitializer
{
public:
MFInitializer()
: _hrCOM(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))
{
_hrMF = MFStartup(MF_VERSION);
}

~MFInitializer()
{
if (SUCCEEDED(_hrMF))
{
MFShutdown();
}

if (SUCCEEDED(_hrCOM))
{
CoUninitialize();
}
}

private:
HRESULT _hrCOM; ///< result of COM initialization
HRESULT _hrMF;  ///< result of Media Foundation Initialization

};

class MFWriter {
public:
MFWriter();
~MFWriter();

void init();
void open();
void close();
void term();
const unsigned char* readbinfile(std::string frame);
bool write(const unsigned char* input);
HRESULT createSinkWriter(UINT32 width, UINT32 height);
void destroySinkWriter();
bool throwIf(HRESULT hr);
CComPtr createMediaBuffer(const unsigned char* const input);
uint32_t computeH264BitRate(const uint32_t quality, uint32_t width, uint32_t height,
double frameRate, size_t bitsPerPixel);

static const char* const FILE_NAME;
static const char* const FRAME_RATE;
static const char* const QUALITY;
static const char* const EXPECTED_FRAME_TYPE;
static const size_t MAX_QUALITY;
static const double INVALID_QUALITY;
static const std::string FRAME_TYPE_FOR_MPEG4;
std::unique_ptr _mfInit;
CComPtr _sinkWriter;
DWORD _videoStreamIndex;
double _frameRate;
UINT32 _quality;
bool _fileSpaceAvailable;
LONGLONG _frameStart;
UINT64 _frameDuration;

};

MFWriter::MFWriter() :
_mfInit(),
_sinkWriter(NULL),
_videoStreamIndex(0),
_frameRate(0),
_quality(0),
_fileSpaceAvailable(true),
_frameStart(0),
_frameDuration(0)
{
}

void MFWriter::init() {
_mfInit.reset(new MFInitializer());
}

void MFWriter::open()
{
_frameRate = 30;
_quality = 75;
_fileSpaceAvailable = true;
}

bool MFWriter::throwIf(HRESULT hr)
{
//prints error and calls exit()
}

bool MFWriter::write(const unsigned char* const input)
{
const size_t width = 320;
const size_t height = 240;
const size_t channels = 3;

if (_sinkWriter == NULL)
{
HRESULT hr = createSinkWriter(static_cast(width), static_cast(height));
// If any failure occurs after the SyncWriter is created, we need to clean it up
// as the device is not closed.
if (FAILED(hr))
{
destroySinkWriter();
return throwIf(hr);
}
}

CComPtr mediaBuffer(createMediaBuffer(input));
MFWRITER_RETURN_ON_ERROR(throwIf(mediaBuffer == NULL ? E_UNEXPECTED : S_OK));

// Create a media sample and add the buffer to the sample.
CComPtr sample;
MFWRITER_RETURN_ON_ERROR(throwIf(MFCreateSample(&sample)));
MFWRITER_RETURN_ON_ERROR(throwIf(sample->AddBuffer(mediaBuffer)));

// Set the time stamp and the duration.
MFWRITER_RETURN_ON_ERROR(throwIf(sample->SetSampleTime(_frameStart)));
MFWRITER_RETURN_ON_ERROR(throwIf(sample->SetSampleDuration(_frameDuration)));

// Send the sample to the Sink Writer.
MFWRITER_RETURN_ON_ERROR(throwIf(_sinkWriter->WriteSample(_videoStreamIndex, sample)));

_frameStart += _frameDuration;

return true;
}

HRESULT MFWriter::createSinkWriter(UINT32 width, UINT32 height)
{
CComPtr pMediaTypeOut;
CComPtr pMediaTypeIn;

std::wstring wideFile = L"sample.mp4";

MFWRITER_RETURN_HRESULT_ON_ERROR(MFCreateSinkWriterFromURL(wideFile.c_str(), NULL, NULL, &_sinkWriter));

// Set the output media type.
MFWRITER_RETURN_HRESULT_ON_ERROR(MFCreateMediaType(&pMediaTypeOut));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, computeH264BitRate(_quality, width, height, _frameRate, 24)));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));

MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, width, height));

_frameDuration = static_cast(std::round((1.0 / _frameRate) * HUNDRED_NANOSECONDS));

// Derive the frame rate from
UINT32 rateNumerator = 0, rateDenominator = 0;
MFWRITER_RETURN_HRESULT_ON_ERROR(MFAverageTimePerFrameToFrameRate(_frameDuration, &rateNumerator, &rateDenominator));

MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, rateNumerator, rateDenominator));

MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));
MFWRITER_RETURN_HRESULT_ON_ERROR(_sinkWriter->AddStream(pMediaTypeOut, &_videoStreamIndex));

// Set the input media type.
MFWRITER_RETURN_HRESULT_ON_ERROR(MFCreateMediaType(&pMediaTypeIn));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2));

MFWRITER_RETURN_HRESULT_ON_ERROR(pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, width, height));
MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, rateNumerator, rateDenominator));
MFWRITER_RETURN_HRESULT_ON_ERROR(MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1));

MFWRITER_RETURN_HRESULT_ON_ERROR(_sinkWriter->SetInputMediaType(_videoStreamIndex, pMediaTypeIn, NULL));

_frameStart = 0;

// Tell the sink writer to start accepting data.
MFWRITER_RETURN_HRESULT_ON_ERROR(_sinkWriter->BeginWriting());

return true;
}

CComPtr MFWriter::createMediaBuffer(const unsigned char* const input)
{
const size_t width = 320;
const size_t height = 240;
const size_t channels = 3;

// Create a new memory buffer.
CComPtr  outputBuffer;
size_t totalBytesInBuffer = height * width * channels * 1;
HRESULT hr = MFCreateMemoryBuffer(static_cast(totalBytesInBuffer), &outputBuffer);
if (FAILED(hr))
{
return NULL;
}

BYTE* outputData = NULL;
hr = outputBuffer->Lock(&outputData, NULL, NULL);
if (FAILED(hr))
{
return NULL;
}

// Copy input data to the Media Sample
// As the input buffer contains data in YUY2 format, the effective width of the frame is doubled.
const LONG bytesPerRow = static_cast(2.0 * width);

hr = MFCopyImage(outputData,                                             // Destination buffer.
bytesPerRow,                                            // Destination stride (bytes per row).
reinterpret_cast(input), // First row in source image.
bytesPerRow,                                            // Source stride.
bytesPerRow,                                            // Image width in bytes.
static_cast(height));        // Image height in pixels.

if (FAILED(hr))
{
return NULL;
}

outputBuffer->Unlock();

// Set the data length of the buffer after writing.
hr = outputBuffer->SetCurrentLength(static_cast(totalBytesInBuffer));
if (FAILED(hr))
{
return NULL;
}

return outputBuffer;
}

int main() {
MFWriter* _mfwrite = new MFWriter();
std::cout 

Подробнее здесь: [url]https://stackoverflow.com/questions/79172804/mediafoundation-timestamp-of-frst-frame-is-not-getting-correctly-set-to-0-inst[/url]
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»