
| ドロップフレーム(NULL frame, Drop frame)について 2004. 8.05 (01版) |
|---|
| NULL frame | ![]() |
| Delta frame | ![]() |
| NULL frame ↓ Key frame | ![]() |
| Delta frame ↓ Key frame | ![]() |
| DLLのデータ領域の使用についての注意点 2004. 8.05 (01版) |
|---|
PVideoFrame __stdcall Sample::GetFrame(int n, IScriptEnvironment* env) {
BYTE buf[720*480*2*2];
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
env->BitBlt(buf, 720*2, src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight());
env->BitBlt(dst->GetWritePtr(), dst->GetPitch(), buf, 720*2, dst->GetRowSize(), dst->GetHeight());
return dst;
}
|

{
1) static bool foo; //--- thread unsafe ---
2) foo = false
if(xxxx) {
foo = true;
//----- proc 1 -----
}
3) if(foo == true) {
//----- proc 2 -----
}
}
|
AVISource("foo.avi")
hogehoge(arg1=10) --- (1)
hogehoge(arg1=20) --- (2)
return last
|
class Sample : public GenericVideoFilter {
AVSValue args;
BYTE buf[720*480*2*2];
public:
Sample(PClip _child, IScriptEnvironment* env) : GenericVideoFilter(_child) {}
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
PVideoFrame __stdcall Sample::GetFrame(int n, IScriptEnvironment* env) {
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
env->BitBlt(buf, 720*2, src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight());
env->BitBlt(dst->GetWritePtr(), dst->GetPitch(), buf, 720*2, dst->GetRowSize(), dst->GetHeight());
return dst;
}
|
class Sample : public GenericVideoFilter {
AVSValue args;
//-------
// BYTE *buf;
//-------
public:
Sample(PClip _child, IScriptEnvironment* env) : GenericVideoFilter(_child) {}
//-------
// Sample(PClip _child, IScriptEnvironment* env)
// : GenericVideoFilter(_child) { buf = new BYTE [720*480*2*2]; }
// ~Sample() { delete [] buf; }
//-------
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
PVideoFrame __stdcall Sample::GetFrame(int n, IScriptEnvironment* env) {
BYTE *buf = new BYTE [720*480*2*2];
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
env->BitBlt(buf, 720*2, src->GetReadPtr(), src->GetPitch(), src->GetRowSize(), src->GetHeight());
env->BitBlt(dst->GetWritePtr(), dst->GetPitch(), buf, 720*2, dst->GetRowSize(), dst->GetHeight());
delete [] buf;
return dst;
}
|
| Clipのデータアライメントの注意点 2004. 8.19 (01版) |
|---|
LoadPlugin("F:\Src\sample\release\sample.dll")
OpenDMLSource("foo.avi")
AssumeFrameBased().ComplementParity()
Crop(2,0,-2,0)
sample()
return last
|
PVideoFrame __stdcall Sample::GetFrame(int n, IScriptEnvironment* env) {
PVideoFrame src = child->GetFrame(n, env);
env->MakeWritable(&src);
char msg[256];
sprintf(msg, "frame=%d GetReadPtr=%08x Offset=%08x", n, src->GetReadPtr(), src->GetOffset());
OutputDebugString(msg);
return src;
}
実行結果
frame=0 GetReadPtr=039d0020 Offset=00000000
frame=1 GetReadPtr=0bd20020 Offset=00000000
frame=2 GetReadPtr=0be60020 Offset=00000000
|
PVideoFrame __stdcall Sample::GetFrame(int n, IScriptEnvironment* env) {
PVideoFrame src = child->GetFrame(n, env);
// env->MakeWritable(&src);
char msg[256];
sprintf(msg, "frame=%d GetReadPtr=%08x Offset=%08x", n, src->GetReadPtr(), src->GetOffset());
OutputDebugString(msg);
return src;
}
実行結果
frame=0 GetReadPtr=03750024 Offset=00000004
frame=1 GetReadPtr=0bbe0024 Offset=00000004
frame=2 GetReadPtr=0bc80024 Offset=00000004
|
----- transform.h -----------------------------------------------------------------
class Crop : public GenericVideoFilter
/**
* Class to crop a video
**/
{
public:
Crop(int _left, int _top, int _width, int _height, int _align, PClip _child, IScriptEnvironment* env);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
static AVSValue __cdecl Create(AVSValue args, void*, IScriptEnvironment* env);
private:
/*const*/ int left_bytes, top, align;
};
|
| クリップの属性変更(1) - VideoInfoとenv->NewVideoFrame() 2004. 8.20 (02版) |
|---|
| 2004. 8.19 (01版) |
| 属性 | 意味 | 値 |
|---|---|---|
| width | 画像の横幅(pixel) | |
| height | 画像の高さ(pixel) | |
| fps_numerator fps_denominator |
画像のフレームレ−ト (fps) |
SetFPS(numerator, denominator) ※ fps = fps_numerator/fps_denominator |
| num_frames | 画像の総フレーム数 | |
| pixel_type | 画像のピクセルタイプ | CS_UNKNOWN = 0 CS_BGR = 1<<28 CS_YUV = 1<<29 CS_INTERLEAVED = 1<<30 CS_PLANAR = 1<<31 CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR CS_I420 = 1<<4 | CS_YUV | CS_PLANAR CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR pixel_typeとThrowError()について参照 |
| audio_samples_per_second | 音声の1秒間あたりのサンプリング数 (周波数 Hz) |
|
| sample_type | 音声のサンプルタイプ | SAMPLE_INT8 = 1<<0 SAMPLE_INT16 = 1<<1 SAMPLE_INT24 = 1<<2 SAMPLE_INT32 = 1<<3 SAMPLE_FLOAT = 1<<4 |
| num_audio_samples | 音声の総サンプル数 | |
| nchannel | 音声のチャンネル数 | |
| image_type | 画像のイメージタイプ | IT_BFF = 1<<0 IT_TFF = 1<<1 IT_FIELDBASED = 1<<2 |
|
Sample::Sample(PClip _child, IScriptEnvironment* env)
: GenericVideoFilter(_child) {
}
PVideoFrame __stdcall Sample::GetFrame(int n, IScriptEnvironment* env) {
vi.width = 320;
vi.height = 240;
vi.SetFPS(30000 * 4, 1001 * 5);
vi.num_frames = vi.fps_numerator * 10 / vi.fps_denominator;
vi.pixel_type = VideoInfo::CS_YUY2;
vi.audio_samples_per_second = 44100;
vi.sample_type = SAMPLE_INT16;
vi.num_audio_samples = vi.AudioSamplesFromFrames(vi.num_frames);
vi.nchannels = 2;
vi.SetFieldBased(false);
vi.Clear(VideoInfo::IT_FIELDBASED);
vi.Set(VideoInfo::IT_TFF);
PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
env->BitBlt(dst->GetWritePtr(), dst->GetPitch(), src->GetReadPtr(), src->GetPitch()
, dst->GetRowSize(), dst->GetHeight());
return dst;
}
|
LoadPlugin("F:\Src\sample\release\sample.dll")
ColorBars(640,480)
ConvertToYUY2()
sample()
return last
|

env->BitBlt(dst->GetWritePtr(), dst->GetPitch(), src->GetReadPtr(), src->GetPitch()
, dst->GetRowSize(), dst->GetHeight());
ここでは、dst->GetRowSize() = 320*2, dst->GetHeight() = 240 になっています。
でもこのフィルタの外に出た場合には、640x480のまま(その他の属性もソースのまま)
になっています。
max(align, 16) : align>0を指定した場合 align * -1 : align<0を指定した場合(17バイト以上、32バイト境界とかにしたい場合、-32を指定)さらに獲得したVideoFrameは初期化されていないことに注意してください。
----- avisynth.cpp -----------------------------------------------------------------
PVideoFrame ScriptEnvironment::NewPlanarVideoFrame(int width, int height, int align, bool U_first) {
int pitch = (width+align-1) / align * align; // Y plane, width = 1 byte per pixel
// int UVpitch = ((width>>1)+align-1) / align * align; // UV plane, width = 1/2 byte per pixel - can't align UV planes seperately.
int UVpitch = pitch>>1; // UV plane, width = 1/2 byte per pixel
int size = pitch * height + UVpitch * height;
VideoFrameBuffer* vfb = GetFrameBuffer(size+(FRAME_ALIGN*4));
if (!vfb)
ThrowError("NewPlanarVideoFrame: Returned 0 size image!");
#ifdef _DEBUG
{
static const BYTE filler[] = { 0x0A, 0x11, 0x0C, 0xA7, 0xED };
BYTE* p = vfb->GetWritePtr();
BYTE* q = p + vfb->GetDataSize()/5*5;
for (; p<q; p+=5) {
p[0]=filler[0]; p[1]=filler[1]; p[2]=filler[2]; p[3]=filler[3]; p[4]=filler[4];
}
}
#endif
// int offset = (-int(vfb->GetWritePtr())) & (align-1); // align first line offset
int offset = int(vfb->GetWritePtr()) & (FRAME_ALIGN-1); // align first line offset
offset = (FRAME_ALIGN - offset)%FRAME_ALIGN;
int Uoffset, Voffset;
if (U_first) {
Uoffset = offset + pitch * height;
Voffset = offset + pitch * height + UVpitch * (height>>1);
} else {
Voffset = offset + pitch * height;
Uoffset = offset + pitch * height + UVpitch * (height>>1);
}
return new VideoFrame(vfb, offset, pitch, width, height, Uoffset, Voffset, UVpitch);
}
PVideoFrame ScriptEnvironment::NewVideoFrame(int row_size, int height, int align) {
int pitch = (row_size+align-1) / align * align;
int size = pitch * height;
VideoFrameBuffer* vfb = GetFrameBuffer(size+(align*4));
#ifdef _DEBUG
{
static const BYTE filler[] = { 0x0A, 0x11, 0x0C, 0xA7, 0xED };
BYTE* p = vfb->GetWritePtr();
BYTE* q = p + vfb->GetDataSize()/5*5;
for (; p<q; p+=5) {
p[0]=filler[0]; p[1]=filler[1]; p[2]=filler[2]; p[3]=filler[3]; p[4]=filler[4];
}
}
#endif
int offset = int(vfb->GetWritePtr()) & (FRAME_ALIGN-1); // align first line offset
offset = (FRAME_ALIGN - offset)%FRAME_ALIGN;
// int offset = (-int(vfb->GetWritePtr())) & (align-1); // align first line offset (alignment is free here!)
return new VideoFrame(vfb, offset, pitch, row_size, height);
}
PVideoFrame __stdcall ScriptEnvironment::NewVideoFrame(const VideoInfo& vi, int align) {
// Check requested pixel_type:
switch (vi.pixel_type) {
case VideoInfo::CS_BGR24:
case VideoInfo::CS_BGR32:
case VideoInfo::CS_YUY2:
case VideoInfo::CS_YV12:
case VideoInfo::CS_I420:
break;
default:
ThrowError("Filter Error: Filter attempted to create VideoFrame with invalid pixel_type.");
}
// If align is negative, it will be forced, if not it may be made bigger
if (vi.IsPlanar()) { // Planar requires different math ;)
if (align<0) {
align *= -1;
} else {
align = max(align,FRAME_ALIGN);
}
if ((vi.height&1)||(vi.width&1))
ThrowError("Filter Error: Attempted to request an YV12 frame that wasn't mod2 in width and height!");
return ScriptEnvironment::NewPlanarVideoFrame(vi.width, vi.height, align, !vi.IsVPlaneFirst()); // If planar, maybe swap U&V
} else {
if ((vi.width&1)&&(vi.IsYUY2()))
ThrowError("Filter Error: Attempted to request an YUY2 frame that wasn't mod2 in width.");
if (align<0) {
align *= -1;
} else {
align = max(align,FRAME_ALIGN);
}
return ScriptEnvironment::NewVideoFrame(vi.RowSize(), vi.height, align);
}
}
------------------------------------------------------------------------------------
|