FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Numpy の配列を利用する C モジュールを作る

Python で大規模な配列を扱う作業をするときは Numpy モジュールによくお世話になります.大抵の場合は Numpy が提供する関数で十分な速度が得られますが,パフォーマンスのために配列へのアクセスをネイティブコードに落としたいことがあります.本記事では Python から C に Numpy 配列を渡し,C 側で結果用の配列を確保して返す方法を説明します.

Keywords: Python, Numpy C-API, 拡張モジュール

続きを読む

スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

Python で方程式を数値的に解く

数値的に方程式を解く方法はいろいろと提案されており,有名なものに二分法やニュートン法(ニュートン・ラフソン法)などがあります.ウェブを調べると,アルゴリズムの原理や実装法などの情報は多く見つかりますが,実装したいわけではない人向けの情報は若干調べ難くなります.本記事では Python 用の科学計算ライブラリである Scipy を用いて方程式を解く方法を説明します.

Keywords: Python, Scipy, Newton-Raphson, bisection



作業環境
・Windows7 Professional 64bit
・Python 3.2.1
・Numpy 1.6.1
・Scipy 0.9.0

次のような関数 f(x) を Newton-Raphson と bisection で解きます.詳しい引数の解説は公式ドキュメントを参考にしてください.
\[
\begin{aligned}
f(x)&=\arctan(2x)+\arctan(x)\\
&=1
\end{aligned}
\]

import math
import scipy.optimize as opt


def main():
f = lambda x : math.atan(2.0 * x) + math.atan(x) - 1.0
fprime = lambda x : 2 / (1 + 4 * x**2) + 1 / (1 + x**2)

x0 = 0.01
a = opt.newton(
f, x0,
fprime=fprime, args=(),
tol=1e-5, maxiter=10000
)

xmin = 0.0
xmax = 0.5
b = opt.bisect(
f,
xmin, xmax,
xtol=1e-8, maxiter=10000
)

print(a, f(a))
print(b, f(b))


if __name__ == '__main__':
main()


結果は以下のようになります.
0.3739474266508991 -1.1233236563157334e-12
0.3739474192261696 -1.6037849048800012e-08

テーマ : プログラミング
ジャンル : コンピュータ

POCO を使って簡単な TCP Server アプリケーションを作る

研究目的などでネットワーク通信を行う必要があると,TCP とテキストで簡単に実装してしまう,ということがよくあります.Java や Python ならば標準ライブラリが充実しているので非常に楽ですが,C/C++ には標準のソケット通信ライブラリがありません.POCO は C++ 用の便利なコンポーネントライブラリで,ネットワークやファイルIOなど様々な機能を提供してくれます.本記事では POCO による TCP Server の作成方法を説明します.

Keywords: POCO, TCP, Server


作業環境
Windows7 Professional 64bit
Visual C++ 2008 Express

本記事で利用する POCO のコンポーネントを以下に列挙します.

 Poco::Net::ServerSocket
 Poco::Net::StreamSocket
 Poco::Net::TCPServer
 Poco::Net::TCPServerConnection
 Poco::Net::TCPServerConnectionFactory

下の2つは利用者が実装する abstract class です.

1.TCPServerConnection の実装

run() メソッドを継承し,クライアントとのやり取りについて記述します.run() メソッドを抜けると TCPServerConnection インスタンスは自動的に破棄されて,接続が自動的に閉じられます.run() メソッド内では socket() メソッドを通じてソケットにアクセスし,データの送受信ができます.

class MyConnection : public TCPServerConnection {
public:
MyConnection(const StreamSocket &socket) : TCPServerConnection(socket)
{
}

virtual ~MyConnection()
{
}

virtual void run()
{
static const char message[] = "This is TCP server sample\n";
socket().sendBytes(message, sizeof(message) - 1);
}
};


2.TCPServerConnectionFactory の実装

createConnection(const StreamSocket&) メソッドを継承します.このメソッドは Factory Method パターンで,TCPServerConnection インスタンスを返すのが仕事です.

class MyConnectionFactory : public TCPServerConnectionFactory {
public:
MyConnectionFactory()
{
}

virtual ~MyConnectionFactory()
{
}

virtual TCPServerConnection* createConnection(const StreamSocket &socket)
{
return new MyConnection(socket);
}
};


3.main.cpp

TCPServer クラスをインスタンス化し,待機状態に入ります.注意点として,TCPServer::start() を呼び出す前に,ServerSocket をリスニング状態にする(listen メソッドを呼ぶ)のを忘れないでください.

int main(int, char**) {
static const Poco::UInt16 SERVER_PORT = 8888;

ServerSocket sock(SERVER_PORT);
sock.listen();

TCPServer server(new MyConnectionFactory(), sock);

printf("Simple TCP Server Application.\n");
printf("command:\n");
printf(" q | quit : Quit application.\n");
printf("\n");

server.start();

bool running = true;
while(running) {
char buff[256];

if(fgets(buff, sizeof(buff), stdin) == NULL) {
running = false;
} else {
buff[strlen(buff) - 1] = '\0';

if(strcmp(buff, "quit") == 0 ||
strcmp(buff, "q") == 0)
{
printf(">> QUIT command accepted.\n");
running = false;
} else {
printf(">> UNKNOWN command.\n");
}
}
}

server.stop();

return 0;
}


4.最後に

私は以前 TCP を書くときには boost の Asio を使っていました.こちらも非常に優れたライブラリ(私にはほとんど魔法)ですが,内部の依存関係が把握できないため,他人にソースを渡すときに膨大なヘッダ群を同梱することになります.これは非常に嫌がられます.その点で POCO はポータビリティが高く,今回のケースでは Foundation と Net だけ同梱すれば,ソースを貰った人はすぐにビルドできます.これはとても気持ちいいことだと思いませんか?

付録 main.cpp
#include <stdio.h>
#include <stdlib.h>

#include <Poco/Net/ServerSocket.h>
#include <Poco/Net/StreamSocket.h>
#include <Poco/Net/TCPServer.h>
#include <Poco/Net/TCPServerConnection.h>
#include <Poco/Net/TCPServerConnectionFactory.h>


using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServer;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;


class MyConnection : public TCPServerConnection {
public:
MyConnection(const StreamSocket &socket) : TCPServerConnection(socket)
{
}

virtual ~MyConnection()
{
}

virtual void run()
{
static const char message[] = "This is TCP server sample\n";
socket().sendBytes(message, sizeof(message) - 1);
}
};


class MyConnectionFactory : public TCPServerConnectionFactory {
public:
MyConnectionFactory()
{
}

virtual ~MyConnectionFactory()
{
}

virtual TCPServerConnection* createConnection(const StreamSocket &socket)
{
return new MyConnection(socket);
}
};


int main(int, char**) {
static const Poco::UInt16 SERVER_PORT = 8888;

ServerSocket sock(SERVER_PORT);
sock.listen();

TCPServer server(new MyConnectionFactory(), sock);

printf("Simple TCP Server Application.\n");
printf("command:\n");
printf(" q | quit : Quit application.\n");
printf("\n");

server.start();

bool running = true;
while(running) {
char buff[256];

if(fgets(buff, sizeof(buff), stdin) == NULL) {
running = false;
} else {
buff[strlen(buff) - 1] = '\0';

if(strcmp(buff, "quit") == 0 ||
strcmp(buff, "q") == 0)
{
printf(">> QUIT command accepted.\n");
running = false;
} else {
printf(">> UNKNOWN command.\n");
}
}
}

server.stop();

return 0;
}

テーマ : プログラミング
ジャンル : コンピュータ

Media Foundation でカメラ画像を取得

Media Foundation は マルチメディアを取り扱うための API セットで,DirectShow の後継になります.今後,DirectShow は Media Foundation に置き換わっていくことが予想されるので,Webカメラのキャプチャを Media Foundation を用いて行いました.

Keywords: Media Foundation, Webカメラ


作業環境
Windows7 Professional 64bit
Visual C++ 2008 Express
Webカメラ BUFFALO BSW32K02HBK

1.ビデオキャプチャデバイスの取得

まずPCに接続されたキャプチャデバイスを取得します.今回は認識されている1番目のキャプチャデバイスを利用します.

[参考:公式ドキュメント Enumerating Video Capture Devices

static HRESULT CreateVideoSource(IMFMediaSource **source) {
IMFMediaSource *src;
IMFAttributes *attr;
IMFActivate **devices;
HRESULT hr;
UINT32 i, count;

*source = NULL;

src = NULL;
attr = NULL;
devices = NULL;
count = 0;

hr = MFCreateAttributes(&attr, 1);
if(FAILED(hr)) goto done;

hr = attr->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if(FAILED(hr)) goto done;

hr = MFEnumDeviceSources(attr, &devices, &count);
if(FAILED(hr)) goto done;

if(count == 0) {
hr = E_FAIL;
goto done;
}

hr = devices[0]->ActivateObject(IID_PPV_ARGS(&src));
if(FAILED(hr)) goto done;

*source = src;

done:
SafeRelease(&attr);

for(i=0; i<count; i++) {
SafeRelease(&devices[i]);
}

CoTaskMemFree(devices);

return hr;
}


2.画像情報

キャプチャデバイスが対応している画像サイズなどの情報は IMFMediaType インターフェースを介して得ることができます.

2.1 IMFMediaType インターフェースを取得します.
[参考:公式ドキュメント How to Set the Video Capture Format

static HRESULT GetCurrentType(
IMFMediaSource *source,
IMFMediaType **type)
{
HRESULT hr;
BOOL selected;
IMFPresentationDescriptor *presDesc = NULL;
IMFStreamDescriptor *strmDesc = NULL;
IMFMediaTypeHandler *handler = NULL;

*type = NULL;

hr = source->CreatePresentationDescriptor(&presDesc);
if(FAILED(hr)) goto done;

hr = presDesc->GetStreamDescriptorByIndex(0, &selected, &strmDesc);
if(FAILED(hr)) goto done;

hr = strmDesc->GetMediaTypeHandler(&handler);
if(FAILED(hr)) goto done;

hr = handler->GetCurrentMediaType(type);
if(FAILED(hr)) goto done;

done:
SafeRelease(&presDesc);
SafeRelease(&strmDesc);
SafeRelease(&handler);

return hr;
}


2.2 IMFMediaType::GetItem に識別子を渡して値を得ます.ここでは画像サイズを得る部分を例示します.
[参考:公式ドキュメント Media Type Debugging Code

static HRESULT GetFrameSize(
IMFMediaType *type,
UINT32 *width,
UINT32 *height)
{
HRESULT hr;
PROPVARIANT var;

*width = 0;
*height = 0;

PropVariantInit(&var);

hr = type->GetItem(MF_MT_FRAME_SIZE, &var);
if(FAILED(hr)) return hr;

Unpack2UINT32AsUINT64(var.uhVal.QuadPart, width, height);

return hr;
}


3.Source Reader

Media Foundation では,メディアの読み出しに Media Session や Source Reader というモデルを利用します.本記事では Source Reader によるデータの取得を行います.

[参考:公式ドキュメント Using the Source Reader to Process Media Data

3.1 IMFSourceReader インターフェースの作成

HRESULT CreateSourceReader(
IMFMediaSource *source,
IMFSourceReader **reader)
{
IMFSourceReader *p;
HRESULT hr;

*reader = NULL;

hr = MFCreateSourceReaderFromMediaSource(source, NULL, &p);
if(FAILED(hr)) {
printf("Failed create IMFSourceReader object\n");
return hr;
}

*reader = p;

return S_OK;
}


3.2 IMFSourceReader::ReadSample
キャプチャデバイスから画像データを読み込みます.本記事では同期モードの利用方法を説明しています.

static HRESULT GetBufferData(IMFSample *sample) {
HRESULT hr;
IMFMediaBuffer *buff;
DWORD maxLen, curLen;
BYTE *memory;

hr = sample->GetBufferByIndex(0, &buff);
if(FAILED(hr)) {
return hr;
}

hr = buff->Lock(&memory, &maxLen, &curLen);
if(FAILED(hr)) goto done;

printf(" Max Length = %d\n", maxLen);
printf(" Curr Length = %d\n", curLen);
printf(" Address = %#x\n", memory);

// Process captured data

hr = buff->Unlock();

done:
SafeRelease(&buff);
return hr;
}


4.最後に
この記事を書くために,カメラの露光時間といったパラメータの設定方法や,YUV - RGB 変換フィルタなど調べましたが,少なくとも私には情報を見つけることができませんでした.現時点では DirectShow の方が機能,情報ともに充実しているように思います.開発者の Media Foundation への移行には,まだ時間がかかるのではないでしょうか?


付録 main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#include <objbase.h>

#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>


typedef enum _VideoFormatType {
VFT_AI44,
VFT_ARGB32,
VFT_AYUV,
VFT_DV25,
VFT_DV50,
VFT_DVH1,
VFT_DVSD,
VFT_DVSL,
VFT_H264,
VFT_I420,
VFT_IYUV,
VFT_M4S2,
VFT_MJPG,
VFT_MP43,
VFT_MP4S,
VFT_MP4V,
VFT_MPG1,
VFT_MSS1,
VFT_MSS2,
VFT_NV11,
VFT_NV12,
VFT_P010,
VFT_P016,
VFT_P210,
VFT_P216,
VFT_RGB24,
VFT_RGB32,
VFT_RGB555,
VFT_RGB565,
VFT_RGB8,
VFT_UYVY,
VFT_v210,
VFT_v410,
VFT_WMV1,
VFT_WMV2,
VFT_WMV3,
VFT_WVC1,
VFT_Y210,
VFT_Y216,
VFT_Y410,
VFT_Y416,
VFT_Y41P,
VFT_Y41T,
VFT_YUY2,
VFT_YV12,
VFT_YVYU,
VFT_NOT_SUPPORTED
} VideoFormatType;


static UINT32 image_width = 0;
static UINT32 image_height = 0;

static INT32 image_stride = 0;
static UINT32 image_length = 0;

static BYTE *image_data = NULL;

static VideoFormatType image_format = VFT_NOT_SUPPORTED;


/*
* This function releases the pointer pp and sets it equal to NULL.
* Another option is to use a smart pointer class, such as CComPtr,
* which is defined in the Active Template Library (ATL).
*
* Note:
* This function is not defined in an SDK header. To use this
* function, you must define it in your own code. It is from here.
* http://msdn.microsoft.com/en-us/library/dd940435%28VS.85%29.aspx
*
* PARAMETERS:
*
* pp[in]
* Pointer of COM component.
*/
template<class T> void SafeRelease(T **pp) {
if(*pp) {
(*pp)->Release();
*pp = NULL;
}
}


/*
* This topic describes how to enumerate the video capture device
* on the user's system, and how create an instance of a device.
* To enumerate the video devices on the system, do the following:
*
* 1. Call MFCreateAttributes to create an attribute store. This
* function receives an IMFAttributes pointer.
*
* 2. Call IMFAttributes::SetGUID to set the MF_DEVSOURCE_-
* ATTRIBUTE_SOURCE_TYPE attribute. Set the attribute value to
* MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID.
*
* 3. Call MFEnumDeviceSources. This function receives an array
* of IMFActivate pointers and the array size. Each pointer
* represents a distinct video capture device.
*
* To create an instance of a capture device:
*
* + Call IMFActivate::ActivateObject to get a pointer to the
* IMFMediaSource interface.
*
* Reference:
* http://msdn.microsoft.com/en-us/library/dd940326.aspx
*/
static HRESULT CreateVideoSource(IMFMediaSource **source) {
IMFMediaSource *src;
IMFAttributes *attr;
IMFActivate **devices;
HRESULT hr;
UINT32 i, count;

*source = NULL;

src = NULL;
attr = NULL;
devices = NULL;
count = 0;

hr = MFCreateAttributes(&attr, 1);
if(FAILED(hr)) goto done;

hr = attr->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
if(FAILED(hr)) goto done;

hr = MFEnumDeviceSources(attr, &devices, &count);
if(FAILED(hr)) goto done;

if(count == 0) {
hr = E_FAIL;
goto done;
}

hr = devices[0]->ActivateObject(IID_PPV_ARGS(&src));
if(FAILED(hr)) goto done;

*source = src;

done:
SafeRelease(&attr);

for(i=0; i<count; i++) {
SafeRelease(&devices[i]);
}

CoTaskMemFree(devices);

return hr;
}


static HRESULT GetCurrentType(
IMFMediaSource *source,
IMFMediaType **type)
{
HRESULT hr;
BOOL selected;
IMFPresentationDescriptor *presDesc = NULL;
IMFStreamDescriptor *strmDesc = NULL;
IMFMediaTypeHandler *handler = NULL;

*type = NULL;

hr = source->CreatePresentationDescriptor(&presDesc);
if(FAILED(hr)) goto done;

hr = presDesc->GetStreamDescriptorByIndex(0, &selected, &strmDesc);
if(FAILED(hr)) goto done;

hr = strmDesc->GetMediaTypeHandler(&handler);
if(FAILED(hr)) goto done;

hr = handler->GetCurrentMediaType(type);
if(FAILED(hr)) goto done;

done:
SafeRelease(&presDesc);
SafeRelease(&strmDesc);
SafeRelease(&handler);

return hr;
}


static HRESULT IsVideoType(IMFMediaType *type, BOOL *b) {
HRESULT hr;
PROPVARIANT var;

*b = FALSE;

PropVariantInit(&var);

hr = type->GetItem(MF_MT_MAJOR_TYPE, &var);
if(FAILED(hr)) return hr;

if(var.vt == VT_CLSID) {
const GUID &guid = *var.puuid;

if(guid == MFMediaType_Video) {
*b = TRUE;
}
}

return hr;
}


static HRESULT GetFrameSize(
IMFMediaType *type,
UINT32 *width,
UINT32 *height)
{
HRESULT hr;
PROPVARIANT var;

*width = 0;
*height = 0;

PropVariantInit(&var);

hr = type->GetItem(MF_MT_FRAME_SIZE, &var);
if(FAILED(hr)) return hr;

Unpack2UINT32AsUINT64(var.uhVal.QuadPart, width, height);

return hr;
}


static HRESULT GetStride(IMFMediaType *type, INT32 *stride) {
HRESULT hr;
PROPVARIANT var;

*stride = 0;

PropVariantInit(&var);

hr = type->GetItem(MF_MT_DEFAULT_STRIDE, &var);
if(FAILED(hr)) return hr;

*stride = (INT32)var.ulVal;

return hr;
}


static HRESULT GetSampleSize(IMFMediaType *type, UINT32 *length) {
HRESULT hr;
PROPVARIANT var;

*length = 0;

PropVariantInit(&var);

hr = type->GetItem(MF_MT_SAMPLE_SIZE, &var);
if(FAILED(hr)) return hr;

*length = var.ulVal;

return hr;
}


#ifndef IF_EQUAL_RETURN
#define IF_EQUAL_RETURN(param, val) if(val == param) return #val
#endif

static LPCSTR GetFormatName(const VideoFormatType &format) {
IF_EQUAL_RETURN(format, VFT_AI44);// FCC('AI44')
IF_EQUAL_RETURN(format, VFT_ARGB32); // D3DFMT_A8R8G8B8
IF_EQUAL_RETURN(format, VFT_AYUV); // FCC('AYUV')
IF_EQUAL_RETURN(format, VFT_DV25); // FCC('dv25')
IF_EQUAL_RETURN(format, VFT_DV50); // FCC('dv50')
IF_EQUAL_RETURN(format, VFT_DVH1); // FCC('dvh1')
IF_EQUAL_RETURN(format, VFT_DVSD); // FCC('dvsd')
IF_EQUAL_RETURN(format, VFT_DVSL); // FCC('dvsl')
IF_EQUAL_RETURN(format, VFT_H264); // FCC('H264')
IF_EQUAL_RETURN(format, VFT_I420); // FCC('I420')
IF_EQUAL_RETURN(format, VFT_IYUV); // FCC('IYUV')
IF_EQUAL_RETURN(format, VFT_M4S2); // FCC('M4S2')
IF_EQUAL_RETURN(format, VFT_MJPG);
IF_EQUAL_RETURN(format, VFT_MP43); // FCC('MP43')
IF_EQUAL_RETURN(format, VFT_MP4S); // FCC('MP4S')
IF_EQUAL_RETURN(format, VFT_MP4V); // FCC('MP4V')
IF_EQUAL_RETURN(format, VFT_MPG1); // FCC('MPG1')
IF_EQUAL_RETURN(format, VFT_MSS1); // FCC('MSS1')
IF_EQUAL_RETURN(format, VFT_MSS2); // FCC('MSS2')
IF_EQUAL_RETURN(format, VFT_NV11); // FCC('NV11')
IF_EQUAL_RETURN(format, VFT_NV12); // FCC('NV12')
IF_EQUAL_RETURN(format, VFT_P010); // FCC('P010')
IF_EQUAL_RETURN(format, VFT_P016); // FCC('P016')
IF_EQUAL_RETURN(format, VFT_P210); // FCC('P210')
IF_EQUAL_RETURN(format, VFT_P216); // FCC('P216')
IF_EQUAL_RETURN(format, VFT_RGB24); // D3DFMT_R8G8B8
IF_EQUAL_RETURN(format, VFT_RGB32); // D3DFMT_X8R8G8B8
IF_EQUAL_RETURN(format, VFT_RGB555); // D3DFMT_X1R5G5B5
IF_EQUAL_RETURN(format, VFT_RGB565); // D3DFMT_R5G6B5
IF_EQUAL_RETURN(format, VFT_RGB8);
IF_EQUAL_RETURN(format, VFT_UYVY); // FCC('UYVY')
IF_EQUAL_RETURN(format, VFT_v210); // FCC('v210')
IF_EQUAL_RETURN(format, VFT_v410); // FCC('v410')
IF_EQUAL_RETURN(format, VFT_WMV1); // FCC('WMV1')
IF_EQUAL_RETURN(format, VFT_WMV2); // FCC('WMV2')
IF_EQUAL_RETURN(format, VFT_WMV3); // FCC('WMV3')
IF_EQUAL_RETURN(format, VFT_WVC1); // FCC('WVC1')
IF_EQUAL_RETURN(format, VFT_Y210); // FCC('Y210')
IF_EQUAL_RETURN(format, VFT_Y216); // FCC('Y216')
IF_EQUAL_RETURN(format, VFT_Y410); // FCC('Y410')
IF_EQUAL_RETURN(format, VFT_Y416); // FCC('Y416')
IF_EQUAL_RETURN(format, VFT_Y41P);
IF_EQUAL_RETURN(format, VFT_Y41T);
IF_EQUAL_RETURN(format, VFT_YUY2); // FCC('YUY2')
IF_EQUAL_RETURN(format, VFT_YV12); // FCC('YV12')
IF_EQUAL_RETURN(format, VFT_YVYU);
IF_EQUAL_RETURN(format, VFT_NOT_SUPPORTED);
return NULL;
}


#ifndef FORMAT_MATCH
#define FORMAT_MATCH(param, val, type) if(val == param) return type
#endif

static VideoFormatType GetFormatType(const GUID &guid) {
FORMAT_MATCH(guid, MFVideoFormat_AI44, VFT_AI44);
FORMAT_MATCH(guid, MFVideoFormat_ARGB32, VFT_ARGB32);
FORMAT_MATCH(guid, MFVideoFormat_AYUV, VFT_AYUV);
FORMAT_MATCH(guid, MFVideoFormat_DV25, VFT_DV25);
FORMAT_MATCH(guid, MFVideoFormat_DV50, VFT_DV50);
FORMAT_MATCH(guid, MFVideoFormat_DVH1, VFT_DVH1);
FORMAT_MATCH(guid, MFVideoFormat_DVSD, VFT_DVSD);
FORMAT_MATCH(guid, MFVideoFormat_DVSL, VFT_DVSL);
FORMAT_MATCH(guid, MFVideoFormat_H264, VFT_H264);
FORMAT_MATCH(guid, MFVideoFormat_I420, VFT_I420);
FORMAT_MATCH(guid, MFVideoFormat_IYUV, VFT_IYUV);
FORMAT_MATCH(guid, MFVideoFormat_M4S2, VFT_M4S2);
FORMAT_MATCH(guid, MFVideoFormat_MJPG, VFT_MJPG);
FORMAT_MATCH(guid, MFVideoFormat_MP43, VFT_MP43);
FORMAT_MATCH(guid, MFVideoFormat_MP4S, VFT_MP4S);
FORMAT_MATCH(guid, MFVideoFormat_MP4V, VFT_MP4V);
FORMAT_MATCH(guid, MFVideoFormat_MPG1, VFT_MPG1);
FORMAT_MATCH(guid, MFVideoFormat_MSS1, VFT_MSS1);
FORMAT_MATCH(guid, MFVideoFormat_MSS2, VFT_MSS2);
FORMAT_MATCH(guid, MFVideoFormat_NV11, VFT_NV11);
FORMAT_MATCH(guid, MFVideoFormat_NV12, VFT_NV12);
FORMAT_MATCH(guid, MFVideoFormat_P010, VFT_P010);
FORMAT_MATCH(guid, MFVideoFormat_P016, VFT_P016);
FORMAT_MATCH(guid, MFVideoFormat_P210, VFT_P210);
FORMAT_MATCH(guid, MFVideoFormat_P216, VFT_P216);
FORMAT_MATCH(guid, MFVideoFormat_RGB24, VFT_RGB24);
FORMAT_MATCH(guid, MFVideoFormat_RGB32, VFT_RGB32);
FORMAT_MATCH(guid, MFVideoFormat_RGB555, VFT_RGB555);
FORMAT_MATCH(guid, MFVideoFormat_RGB565, VFT_RGB565);
FORMAT_MATCH(guid, MFVideoFormat_RGB8, VFT_RGB8);
FORMAT_MATCH(guid, MFVideoFormat_UYVY, VFT_UYVY);
FORMAT_MATCH(guid, MFVideoFormat_v210, VFT_v210);
FORMAT_MATCH(guid, MFVideoFormat_v410, VFT_v410);
FORMAT_MATCH(guid, MFVideoFormat_WMV1, VFT_WMV1);
FORMAT_MATCH(guid, MFVideoFormat_WMV2, VFT_WMV2);
FORMAT_MATCH(guid, MFVideoFormat_WMV3, VFT_WMV3);
FORMAT_MATCH(guid, MFVideoFormat_WVC1, VFT_WVC1);
FORMAT_MATCH(guid, MFVideoFormat_Y210, VFT_Y210);
FORMAT_MATCH(guid, MFVideoFormat_Y216, VFT_Y216);
FORMAT_MATCH(guid, MFVideoFormat_Y410, VFT_Y410);
FORMAT_MATCH(guid, MFVideoFormat_Y416, VFT_Y416);
FORMAT_MATCH(guid, MFVideoFormat_Y41P, VFT_Y41P);
FORMAT_MATCH(guid, MFVideoFormat_Y41T, VFT_Y41T);
FORMAT_MATCH(guid, MFVideoFormat_YUY2, VFT_YUY2);
FORMAT_MATCH(guid, MFVideoFormat_YV12, VFT_YV12);
FORMAT_MATCH(guid, MFVideoFormat_YVYU, VFT_YVYU);
return VFT_NOT_SUPPORTED;
}


static HRESULT GetVideoFormat(IMFMediaType *type, VideoFormatType *format) {
HRESULT hr;
PROPVARIANT var;

PropVariantInit(&var);

hr = type->GetItem(MF_MT_SUBTYPE, &var);
if(FAILED(hr)) return hr;

if(var.vt == VT_CLSID) {
*format = GetFormatType(*var.puuid);
} else {
hr = E_FAIL;
}

return hr;
}


static HRESULT GetMediaFormat(IMFMediaType *type) {
HRESULT hr;
BOOL isVideo;

hr = IsVideoType(type, &isVideo);
if(!isVideo) return E_FAIL;

printf("Media Type\n");

hr = GetVideoFormat(type, &image_format);
if(SUCCEEDED(hr)) {
printf(" Video format = %s\n", GetFormatName(image_format));
}

hr = GetFrameSize(type, &image_width, &image_height);
if(SUCCEEDED(hr)) {
printf(" Frame size = %d x %d\n", image_width, image_height);
}

hr = GetStride(type, &image_stride);
if(SUCCEEDED(hr)) {
printf(" Stride = %d\n", image_stride);
}

hr = GetSampleSize(type, &image_length);
if(SUCCEEDED(hr)) {
printf(" Sample Size = %d\n", image_length);
}

return hr;
}


HRESULT CreateSourceReader(
IMFMediaSource *source,
IMFSourceReader **reader)
{
IMFSourceReader *p;
HRESULT hr;

*reader = NULL;

hr = MFCreateSourceReaderFromMediaSource(source, NULL, &p);
if(FAILED(hr)) {
printf("Failed create IMFSourceReader object\n");
return hr;
}

*reader = p;

return S_OK;
}


static HRESULT GetBufferData(IMFSample *sample) {
HRESULT hr;
IMFMediaBuffer *buff;
DWORD maxLen, curLen;
BYTE *memory;

hr = sample->GetBufferByIndex(0, &buff);
if(FAILED(hr)) {
return hr;
}

hr = buff->Lock(&memory, &maxLen, &curLen);
if(FAILED(hr)) goto done;

printf(" Max Length = %d\n", maxLen);
printf(" Curr Length = %d\n", curLen);
printf(" Address = %#x\n", memory);

hr = buff->Unlock();

done:
SafeRelease(&buff);
return hr;
}


static void MainLoop(IMFSourceReader *reader) {
IMFSample *sample;
DWORD streamIndex, flags;
LONGLONG timeStamp;
HRESULT hr;

for(int i=0; i<10; i++) {
hr = reader->ReadSample(
(DWORD)MF_SOURCE_READER_ANY_STREAM,
0,
&streamIndex,
&flags,
&timeStamp,
&sample);

if(SUCCEEDED(hr)) {
printf("Frame %d:\n", i);
printf(" Stream Index = %u\n", streamIndex);
printf(" Flags = %u\n", flags);
printf(" Time Stamp = %u\n", timeStamp);

if(sample) {
GetBufferData(sample);
}

SafeRelease(&sample);
}
}
}


int main(int, char**) {
HRESULT hr;
IMFMediaSource *source;
IMFMediaType *type;

hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if(FAILED(hr)) {
printf("Failed initializing COM components\n");
exit(1);
}

hr = MFStartup(MF_VERSION);
if(FAILED(hr)) {
printf("Failed start up Media Foundation\n");
exit(1);
}

if(SUCCEEDED(CreateVideoSource(&source)) &&
SUCCEEDED(GetCurrentType(source, &type)) &&
SUCCEEDED(GetMediaFormat(type)))
{
IMFSourceReader *reader;

hr = CreateSourceReader(source, &reader);
if(SUCCEEDED(hr)) {
MainLoop(reader);

SafeRelease(&reader);
SafeRelease(&type);
SafeRelease(&source);
} else {
/*
* Some Microsoft Media Foundation objects must be shut
* down before being released. If so, the caller is
* responsible for shutting down the object that is returned
* in ppv. To shut down the object, do one of the following:
*
* + Call IMFActivate::ShutdownObject on the activation object
*
* + Call the object-specific shutdown method. This method will
* depend on the type of object.
*/
source->Shutdown();

SafeRelease(&type);
SafeRelease(&source);
}
}

MFShutdown();

CoUninitialize();

return 0;
}

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

Ishida Akihiko

Author:Ishida Akihiko
FC2ブログへようこそ!

免責事項
当サイトに掲載する記事内容は,必ずしも正確性,信頼性,妥当性,有用性,完成度などを保証しません.記事の利用はすべて自己責任でお願いします.当サイトに掲載された内容によって発生したいかなる損害に対しても,管理人は一切の責任を負いかねます.
最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
アクセスカウンター
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。