Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu öğreticide, video akışı için H.264 ve ses akışı için AAC kullanarak MP4 dosyasını kodlamak için Transcode API'sinin nasıl kullanılacağı gösterilmektedir.
- Başlık Dosyaları ve Kütüphane Dosyaları
- Kodlama Profillerini Tanımlama
- wmain İşlevini Yazın
- Dosyayı Kodlama
- Medya Oturumu Yardımcısı
- İlgili konular
Üst Bilgiler ve Kitaplık Dosyaları
Aşağıdaki üst bilgi dosyalarını ekleyin.
#include <new>
#include <iostream>
#include <windows.h>
#include <mfapi.h>
#include <Mfidl.h>
#include <shlwapi.h>
Aşağıdaki kitaplık dosyalarını bağlayın.
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mf")
#pragma comment(lib, "mfuuid")
#pragma comment(lib, "shlwapi")
Kodlama Profillerini Tanımlama
Kodlamaya yönelik yaklaşımlardan biri, önceden bilinen hedef kodlama profillerinin listesini tanımlamaktır. Bu öğreticide, nispeten basit bir yaklaşım benimseyeceğiz ve H.264 video ve AAC ses kodlama biçimlerinin listesini depolayacağız.
H.264 için en önemli biçim öznitelikleri H.264 profili, kare hızı, kare boyutu ve kodlanmış bit hızıdır. Aşağıdaki dizi H.264 kodlama biçimlerinin listesini içerir.
struct H264ProfileInfo
{
UINT32 profile;
MFRatio fps;
MFRatio frame_size;
UINT32 bitrate;
};
H264ProfileInfo h264_profiles[] =
{
{ eAVEncH264VProfile_Base, { 15, 1 }, { 176, 144 }, 128000 },
{ eAVEncH264VProfile_Base, { 15, 1 }, { 352, 288 }, 384000 },
{ eAVEncH264VProfile_Base, { 30, 1 }, { 352, 288 }, 384000 },
{ eAVEncH264VProfile_Base, { 29970, 1000 }, { 320, 240 }, 528560 },
{ eAVEncH264VProfile_Base, { 15, 1 }, { 720, 576 }, 4000000 },
{ eAVEncH264VProfile_Main, { 25, 1 }, { 720, 576 }, 10000000 },
{ eAVEncH264VProfile_Main, { 30, 1 }, { 352, 288 }, 10000000 },
};
H.264 profilleri eAVEncH264VProfile sabit listesi kullanılarak belirtilir. H.264 düzeyini de belirtebilirsiniz, ancak Microsoft Media Foundation H.264 Video Kodlayıcısı belirli bir video akışı için uygun düzeyi türetebilir, bu nedenle kodlayıcının seçili düzeyini geçersiz kılmamanızı öneririz. Geçişli içerik için, araya alma modunu da belirtebilirsiniz (bkz. Video Araya Geçirme).
AAC ses için en önemli biçim öznitelikleri ses örnek hızı, kanal sayısı, örnek başına bit sayısı ve kodlanmış bit hızıdır. İsteğe bağlı olarak, AAC ses profili düzeyi göstergesini ayarlayabilirsiniz. Daha fazla bilgi için bkz. AAC Kodlayıcı. Aşağıdaki dizi, AAC kodlama biçimlerinin listesini içerir.
struct AACProfileInfo
{
UINT32 samplesPerSec;
UINT32 numChannels;
UINT32 bitsPerSample;
UINT32 bytesPerSec;
UINT32 aacProfile;
};
AACProfileInfo aac_profiles[] =
{
{ 96000, 2, 16, 24000, 0x29},
{ 48000, 2, 16, 24000, 0x29},
{ 44100, 2, 16, 16000, 0x29},
{ 44100, 2, 16, 12000, 0x29},
};
Uyarı
H264ProfileInfo Burada tanımlanan ve AACProfileInfo yapıları Media Foundation API'sinin bir parçası değildir.
wmain İşlevini yazma
Aşağıdaki kod, konsol uygulamasının giriş noktasını gösterir.
int video_profile = 0;
int audio_profile = 0;
int wmain(int argc, wchar_t* argv[])
{
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
if (argc < 3 || argc > 5)
{
std::cout << "Usage:" << std::endl;
std::cout << "input output [ audio_profile video_profile ]" << std::endl;
return 1;
}
if (argc > 3)
{
audio_profile = _wtoi(argv[3]);
}
if (argc > 4)
{
video_profile = _wtoi(argv[4]);
}
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
if (SUCCEEDED(hr))
{
hr = EncodeFile(argv[1], argv[2]);
MFShutdown();
}
CoUninitialize();
}
if (SUCCEEDED(hr))
{
std::cout << "Done." << std::endl;
}
else
{
std::cout << "Error: " << std::hex << hr << std::endl;
}
return 0;
}
wmain işlevi aşağıdakileri yapar:
- COM kitaplığını başlatmak için CoInitializeEx işlevini çağırır.
- Media Foundation'ı başlatmak için MFStartup işlevini çağırır.
- Uygulama tanımlı
EncodeFileişlevi çağırır. Bu işlev giriş dosyasını çıkış dosyasına dönüştürür ve sonraki bölümde gösterilir. - Media Foundation'ı kapatmak için MFShutdown işlevini çağırır.
- COM kitaplığını sonlandırmak için CoUninitialize işlevini çağırın.
Dosyayı Kodlama
Aşağıdaki kod, kodlamayı dönüştürme işlemini gerçekleştiren işlevi gösterir EncodeFile . Bu işlev, çoğunlukla bu konunun ilerleyen bölümlerinde gösterilen diğer uygulama tanımlı işlevlere yapılan çağrılardan oluşur.
HRESULT EncodeFile(PCWSTR pszInput, PCWSTR pszOutput)
{
IMFTranscodeProfile *pProfile = NULL;
IMFMediaSource *pSource = NULL;
IMFTopology *pTopology = NULL;
CSession *pSession = NULL;
MFTIME duration = 0;
HRESULT hr = CreateMediaSource(pszInput, &pSource);
if (FAILED(hr))
{
goto done;
}
hr = GetSourceDuration(pSource, &duration);
if (FAILED(hr))
{
goto done;
}
hr = CreateTranscodeProfile(&pProfile);
if (FAILED(hr))
{
goto done;
}
hr = MFCreateTranscodeTopology(pSource, pszOutput, pProfile, &pTopology);
if (FAILED(hr))
{
goto done;
}
hr = CSession::Create(&pSession);
if (FAILED(hr))
{
goto done;
}
hr = pSession->StartEncodingSession(pTopology);
if (FAILED(hr))
{
goto done;
}
hr = RunEncodingSession(pSession, duration);
done:
if (pSource)
{
pSource->Shutdown();
}
SafeRelease(&pSession);
SafeRelease(&pProfile);
SafeRelease(&pSource);
SafeRelease(&pTopology);
return hr;
}
EncodeFile işlevi aşağıdaki adımları gerçekleştirir.
- Giriş dosyasının URL'sini veya dosya yolunu kullanarak giriş dosyası için bir medya kaynağı oluşturur. (Bkz. Medya Kaynağını Oluşturma.)
- Giriş dosyasının süresini alır. (Bkz. Kaynak Süresini Alma.)
- Kod dönüştürme profilini oluşturun. (Bkz . Transcode Profili Oluşturma.)
- Kısmi kod dönüştürme topolojisini oluşturmak için MFCreateTranscodeTopology çağrısında bulunur.
- Medya Oturumunu yöneten bir yardımcı nesnesi oluşturun. (Bkz. Medya Oturumu Yardımcısı).
- Kodlama oturumunu çalıştırın ve tamamlanmasını bekleyin. (Bkz . Kodlama Oturumunu Çalıştırma.)
- Medya kaynağını kapatmak için IMFMediaSource::Shutdown çağrısını kullanın.
- Arabirim işaretçilerini serbest bırakın. Bu kod, arabirim işaretçilerini serbest bırakmak için SafeRelease işlevini kullanır. Bir diğer seçenek de CComPtr gibi bir COM akıllı işaretçi sınıfı kullanmaktır.
Medya Kaynağı Oluşturma
Medya kaynağı, giriş dosyasını okuyan ve ayrıştıran nesnedir. Medya kaynağını oluşturmak için giriş dosyasının URL'sini Kaynak Çözümleyici'ye geçirin. Aşağıdaki kod bunun nasıl yapılacağını gösterir.
HRESULT CreateMediaSource(PCWSTR pszURL, IMFMediaSource **ppSource)
{
MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;
IMFSourceResolver* pResolver = NULL;
IUnknown* pSource = NULL;
// Create the source resolver.
HRESULT hr = MFCreateSourceResolver(&pResolver);
if (FAILED(hr))
{
goto done;
}
// Use the source resolver to create the media source
hr = pResolver->CreateObjectFromURL(pszURL, MF_RESOLUTION_MEDIASOURCE,
NULL, &ObjectType, &pSource);
if (FAILED(hr))
{
goto done;
}
// Get the IMFMediaSource interface from the media source.
hr = pSource->QueryInterface(IID_PPV_ARGS(ppSource));
done:
SafeRelease(&pResolver);
SafeRelease(&pSource);
return hr;
}
Daha fazla bilgi için bkz. kaynak çözümleyiciyi kullanma .
Kaynak Süresini Alma
Gerekli olmasa da, giriş dosyasının süresi boyunca medya kaynağını sorgulamak yararlı olur. Bu değer kodlama ilerleme durumunu izlemek için kullanılabilir. Süre, sunu tanımlayıcısının MF_PD_DURATION özniteliğinde depolanır. IMFMediaSource::CreatePresentationDescriptor'ı çağırarak sunu tanımlayıcısını alın.
HRESULT GetSourceDuration(IMFMediaSource *pSource, MFTIME *pDuration)
{
*pDuration = 0;
IMFPresentationDescriptor *pPD = NULL;
HRESULT hr = pSource->CreatePresentationDescriptor(&pPD);
if (SUCCEEDED(hr))
{
hr = pPD->GetUINT64(MF_PD_DURATION, (UINT64*)pDuration);
pPD->Release();
}
return hr;
}
Kod Dönüştürme Profili Oluşturma
Kod dönüştürme profili kodlama parametrelerini açıklar. Kod dönüştürme profili oluşturma hakkında daha fazla bilgi için bkz. Transcode API'sini kullanma. Profili oluşturmak için aşağıdaki adımları uygulayın.
- Boş profili oluşturmak için MFCreateTranscodeProfile'ı çağırın.
- AAC ses akışı için bir medya türü oluşturun. BUNU, IMFTranscodeProfile::SetAudioAttributes çağrısı yaparak profile ekleyin.
- H.264 video akışı için bir medya türü oluşturun. BUNU, IMFTranscodeProfile::SetVideoAttributes çağrısı yaparak profile ekleyin.
- Kapsayıcı düzeyi öznitelikleri için bir öznitelik deposu oluşturmak üzere MFCreateAttributesçağırın.
- MF_TRANSCODE_CONTAINERTYPE özniteliğini ayarlayın. Gerekli olan tek kapsayıcı düzeyi öznitelik budur. MP4 dosya çıkışı için bu özniteliği MFTranscodeContainerType_MPEG4 olarak ayarlayın.
- Kapsayıcı düzeyi özniteliklerini ayarlamak için IMFTranscodeProfile::SetContainerAttributes çağrısı yapın.
Aşağıdaki kodda bu adımlar gösterilmektedir.
HRESULT CreateTranscodeProfile(IMFTranscodeProfile **ppProfile)
{
IMFTranscodeProfile *pProfile = NULL;
IMFAttributes *pAudio = NULL;
IMFAttributes *pVideo = NULL;
IMFAttributes *pContainer = NULL;
HRESULT hr = MFCreateTranscodeProfile(&pProfile);
if (FAILED(hr))
{
goto done;
}
// Audio attributes.
hr = CreateAACProfile(audio_profile, &pAudio);
if (FAILED(hr))
{
goto done;
}
hr = pProfile->SetAudioAttributes(pAudio);
if (FAILED(hr))
{
goto done;
}
// Video attributes.
hr = CreateH264Profile(video_profile, &pVideo);
if (FAILED(hr))
{
goto done;
}
hr = pProfile->SetVideoAttributes(pVideo);
if (FAILED(hr))
{
goto done;
}
// Container attributes.
hr = MFCreateAttributes(&pContainer, 1);
if (FAILED(hr))
{
goto done;
}
hr = pContainer->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_MPEG4);
if (FAILED(hr))
{
goto done;
}
hr = pProfile->SetContainerAttributes(pContainer);
if (FAILED(hr))
{
goto done;
}
*ppProfile = pProfile;
(*ppProfile)->AddRef();
done:
SafeRelease(&pProfile);
SafeRelease(&pAudio);
SafeRelease(&pVideo);
SafeRelease(&pContainer);
return hr;
}
H.264 video akışının özniteliklerini belirtmek için bir öznitelik deposu oluşturun ve aşağıdaki öznitelikleri ayarlayın:
| Özellik | Açıklama |
|---|---|
| MF_MT_SUBTYPE | MFVideoFormat_H264 olarak ayarlayın. |
| MF_MT_MPEG2_PROFILE | H.264 profili. |
| MF_MT_FRAME_SIZE | Çerçeve boyutu. |
| MF_MT_FRAME_RATE | Kare hızı. |
| MF_MT_AVG_BITRATE | Kodlanmış bit hızı. |
AAC ses akışının özniteliklerini belirtmek için bir öznitelik deposu oluşturun ve aşağıdaki öznitelikleri ayarlayın:
| Özellik | Açıklama |
|---|---|
| MF_MT_SUBTYPE | MFAudioFormat_AAC olarak ayarla |
| MF_MT_AUDIO_ÖRNEKLERİ_SANIYE_BAŞINA | Ses örnek hızı. |
| MF_MT_AUDIO_BITS_PER_SAMPLE | Ses örneği başına bit sayısı. |
| MF_MT_AUDIO_NUM_CHANNELS | Ses kanalı sayısı. |
| MF_MT_AUDIO_AVG_BYTES_PER_SECOND | Kodlanmış bit hızı. |
| MF_MT_AUDIO_BLOCK_ALIGNMENT | 1 olarak ayarlayın. |
| AAC Ses Profil-Seviye Göstergesi | AAC profil düzeyi göstergesi (isteğe bağlı). |
Aşağıdaki kod video akışı özniteliklerini oluşturur.
HRESULT CreateH264Profile(DWORD index, IMFAttributes **ppAttributes)
{
if (index >= ARRAYSIZE(h264_profiles))
{
return E_INVALIDARG;
}
IMFAttributes *pAttributes = NULL;
const H264ProfileInfo& profile = h264_profiles[index];
HRESULT hr = MFCreateAttributes(&pAttributes, 5);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(MF_MT_MPEG2_PROFILE, profile.profile);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeSize(
pAttributes, MF_MT_FRAME_SIZE,
profile.frame_size.Numerator, profile.frame_size.Numerator);
}
if (SUCCEEDED(hr))
{
hr = MFSetAttributeRatio(
pAttributes, MF_MT_FRAME_RATE,
profile.fps.Numerator, profile.fps.Denominator);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(MF_MT_AVG_BITRATE, profile.bitrate);
}
if (SUCCEEDED(hr))
{
*ppAttributes = pAttributes;
(*ppAttributes)->AddRef();
}
SafeRelease(&pAttributes);
return hr;
}
Aşağıdaki kod ses akışı özniteliklerini oluşturur.
HRESULT CreateAACProfile(DWORD index, IMFAttributes **ppAttributes)
{
if (index >= ARRAYSIZE(aac_profiles))
{
return E_INVALIDARG;
}
const AACProfileInfo& profile = aac_profiles[index];
IMFAttributes *pAttributes = NULL;
HRESULT hr = MFCreateAttributes(&pAttributes, 7);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(
MF_MT_AUDIO_BITS_PER_SAMPLE, profile.bitsPerSample);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(
MF_MT_AUDIO_SAMPLES_PER_SECOND, profile.samplesPerSec);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(
MF_MT_AUDIO_NUM_CHANNELS, profile.numChannels);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(
MF_MT_AUDIO_AVG_BYTES_PER_SECOND, profile.bytesPerSec);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(
MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, profile.aacProfile);
}
if (SUCCEEDED(hr))
{
*ppAttributes = pAttributes;
(*ppAttributes)->AddRef();
}
SafeRelease(&pAttributes);
return hr;
}
Kod dönüştürme API'sinin gerçek bir medya türü gerektirmediğini, ancak medya türü öznitelikleri kullandığını unutmayın. SetVideoAttributes ve SetAudioAttributes yöntemleri ana türü ifade ettiğinden, özellikle MF_MT_MAJOR_TYPE özniteliği gerekli değildir. Ancak, bu yöntemlere gerçek bir medya türü geçirme işlemi de kabul edilebilir. ( IMFMediaType arabirimi , IMFAttributes'i devralır.)
Kodlama Oturumunu Çalıştırma
Aşağıdaki kod kodlama oturumunu çalıştırır. Sonraki bölümde gösterilen Medya Oturumu yardımcı sınıfını kullanır.
HRESULT RunEncodingSession(CSession *pSession, MFTIME duration)
{
const DWORD WAIT_PERIOD = 500;
const int UPDATE_INCR = 5;
HRESULT hr = S_OK;
MFTIME pos;
LONGLONG prev = 0;
while (1)
{
hr = pSession->Wait(WAIT_PERIOD);
if (hr == E_PENDING)
{
hr = pSession->GetEncodingPosition(&pos);
LONGLONG percent = (100 * pos) / duration ;
if (percent >= prev + UPDATE_INCR)
{
std::cout << percent << "% .. ";
prev = percent;
}
}
else
{
std::cout << std::endl;
break;
}
}
return hr;
}
Medya Oturumu Yardımcısı
Medya Oturumu, bu belgelerin Media Foundation Mimarisi bölümünde daha ayrıntılı olarak açıklanmıştır. Medya Oturumu zaman uyumsuz bir olay modeli kullanır. Bir GUI uygulamasında, kullanıcı arabirimi iş parçacığının sonraki olayı beklemesini engellemeden oturum olaylarına yanıt vermelisiniz. Korumasız Medya Dosyalarını Yürütme öğreticisi, bir kayıttan yürütme uygulamasında bunun nasıl yapıldığını gösterir. Kodlama için ilke aynıdır, ancak daha az olay geçerlidir:
| Etkinlik | Açıklama |
|---|---|
| MESessionEnded | Kodlama tamamlandığında tetiklenir. |
| MESessionClosed | IMFMediaSession::Close yöntemi tamamlandığında tetiklenir. Bu olay başlatıldıktan sonra Medya Oturumu'nı kapatmak güvenlidir. |
Konsol uygulaması için olayları engellemek ve beklemek mantıklıdır. Kaynak dosyaya ve kodlama ayarlarına bağlı olarak kodlamanın tamamlanması biraz zaman alabilir. İlerleme güncelleştirmelerini aşağıdaki gibi alabilirsiniz:
- Sunu saatini almak için IMFMediaSession::GetClock çağrısı yapın.
- IMFPresentationClock arabiriminin saatini sorgula.
- Geçerli konumu almak için IMFPresentationClock::GetTime'ı çağırın.
- Konum, zaman birimi cinsinden verilir. Tamamlanma yüzdesini almak için değerini
(100 * position) / durationkullanın.
İşte CSession sınıfının bildirimi.
class CSession : public IMFAsyncCallback
{
public:
static HRESULT Create(CSession **ppSession);
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IMFAsyncCallback methods
STDMETHODIMP GetParameters(DWORD* pdwFlags, DWORD* pdwQueue)
{
// Implementation of this method is optional.
return E_NOTIMPL;
}
STDMETHODIMP Invoke(IMFAsyncResult *pResult);
// Other methods
HRESULT StartEncodingSession(IMFTopology *pTopology);
HRESULT GetEncodingPosition(MFTIME *pTime);
HRESULT Wait(DWORD dwMsec);
private:
CSession() : m_cRef(1), m_pSession(NULL), m_pClock(NULL), m_hrStatus(S_OK), m_hWaitEvent(NULL)
{
}
virtual ~CSession()
{
if (m_pSession)
{
m_pSession->Shutdown();
}
SafeRelease(&m_pClock);
SafeRelease(&m_pSession);
CloseHandle(m_hWaitEvent);
}
HRESULT Initialize();
private:
IMFMediaSession *m_pSession;
IMFPresentationClock *m_pClock;
HRESULT m_hrStatus;
HANDLE m_hWaitEvent;
long m_cRef;
};
Aşağıdaki kod, sınıfın tam uygulamasını CSession gösterir.
HRESULT CSession::Create(CSession **ppSession)
{
*ppSession = NULL;
CSession *pSession = new (std::nothrow) CSession();
if (pSession == NULL)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pSession->Initialize();
if (FAILED(hr))
{
pSession->Release();
return hr;
}
*ppSession = pSession;
return S_OK;
}
STDMETHODIMP CSession::QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(CSession, IMFAsyncCallback),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) CSession::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CSession::Release()
{
long cRef = InterlockedDecrement(&m_cRef);
if (cRef == 0)
{
delete this;
}
return cRef;
}
HRESULT CSession::Initialize()
{
IMFClock *pClock = NULL;
HRESULT hr = MFCreateMediaSession(NULL, &m_pSession);
if (FAILED(hr))
{
goto done;
}
hr = m_pSession->GetClock(&pClock);
if (FAILED(hr))
{
goto done;
}
hr = pClock->QueryInterface(IID_PPV_ARGS(&m_pClock));
if (FAILED(hr))
{
goto done;
}
hr = m_pSession->BeginGetEvent(this, NULL);
if (FAILED(hr))
{
goto done;
}
m_hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hWaitEvent == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
done:
SafeRelease(&pClock);
return hr;
}
// Implements IMFAsyncCallback::Invoke
STDMETHODIMP CSession::Invoke(IMFAsyncResult *pResult)
{
IMFMediaEvent* pEvent = NULL;
MediaEventType meType = MEUnknown;
HRESULT hrStatus = S_OK;
HRESULT hr = m_pSession->EndGetEvent(pResult, &pEvent);
if (FAILED(hr))
{
goto done;
}
hr = pEvent->GetType(&meType);
if (FAILED(hr))
{
goto done;
}
hr = pEvent->GetStatus(&hrStatus);
if (FAILED(hr))
{
goto done;
}
if (FAILED(hrStatus))
{
hr = hrStatus;
goto done;
}
switch (meType)
{
case MESessionEnded:
hr = m_pSession->Close();
if (FAILED(hr))
{
goto done;
}
break;
case MESessionClosed:
SetEvent(m_hWaitEvent);
break;
}
if (meType != MESessionClosed)
{
hr = m_pSession->BeginGetEvent(this, NULL);
}
done:
if (FAILED(hr))
{
m_hrStatus = hr;
m_pSession->Close();
}
SafeRelease(&pEvent);
return hr;
}
HRESULT CSession::StartEncodingSession(IMFTopology *pTopology)
{
HRESULT hr = m_pSession->SetTopology(0, pTopology);
if (SUCCEEDED(hr))
{
PROPVARIANT varStart;
PropVariantClear(&varStart);
hr = m_pSession->Start(&GUID_NULL, &varStart);
}
return hr;
}
HRESULT CSession::GetEncodingPosition(MFTIME *pTime)
{
return m_pClock->GetTime(pTime);
}
HRESULT CSession::Wait(DWORD dwMsec)
{
HRESULT hr = S_OK;
DWORD dwTimeoutStatus = WaitForSingleObject(m_hWaitEvent, dwMsec);
if (dwTimeoutStatus != WAIT_OBJECT_0)
{
hr = E_PENDING;
}
else
{
hr = m_hrStatus;
}
return hr;
}
İlgili konular