Win32 API 日本語リファレンス
ホームMedia.DirectShow › AM_SimpleRateChange

AM_SimpleRateChange

構造体
サイズx64: 16 バイト / x86: 16 バイト

サイズ=各フィールドのバイト数(x64/x86 で異なる場合は x64/x86 と併記)。x64/x86 列=フィールドのバイトオフセット(HSPで dupptr / lpoke / wpoke 等に使用)。

フィールド

フィールドサイズx64x86説明
StartTimeLONGLONG8+0+0新しいレートが有効になる入力サンプルのタイムスタンプを指定します。新しいレートは、タイムスタンプが >= StartTime であり、かつ次にキューに入れられたレートセグメントの開始時刻より小さいすべてのサンプルに適用されます。
RateINT4+8+8新しいレート × 10000 を指定します。レートは速度の逆数です。たとえば、再生速度が 2x の場合、レートは 1/2 になるため、Rate メンバーには 5000 を設定します。

公式ドキュメント

[このページに関連する機能である DirectShow は、レガシー機能です。これは MediaPlayerIMFMediaEngine、および Audio/Video Capture in Media Foundation に置き換えられました。これらの機能は Windows 10 および Windows 11 向けに最適化されています。Microsoft は、可能な場合は新しいコードで DirectShow ではなく MediaPlayerIMFMediaEngineAudio/Video Capture in Media Foundation を使用することを強く推奨します。レガシー API を使用している既存のコードについても、可能であれば新しい API を使用するように書き換えることを推奨します。]

AM_SimpleRateChange 構造体は、MPEG-2 ストリームの再生レートを変更するために使用します。

解説(Remarks)

バージョン 1.1 のセマンティクス

このプロパティセットのバージョン 1.1 では、StartTime メンバーに -1 を指定できます。この値は、レート変更がデコーダーの 最も先行する サンプル、つまりデコーダーの出力キューの先頭にあるサンプルに適用されることを示します。レート変更の実際の開始時刻を取得するには、AM_RATE_QueryLastRateSegPTS プロパティを照会します。

デコーダーは、キューに入っているすべてのサンプルのタイムスタンプを新しいレートに合わせて調整する必要があります。特にオーディオデコーダーでは、キューに入っているサンプルが新しいレートと互換性を持たない場合があります。その場合、デコーダーはキューに入っているサンプルを単純に破棄してもかまいません。サンプルを破棄した後は、最初に配信するサンプルに不連続フラグを設定する必要があります。

StartTime が -1 であるものの、新しいレートに互換性がなく、デコーダーがサンプルのキューを保持していない場合、デコーダーは VFW_E_DVD_WRONG_SPEEDIKsPropertySet::Set メソッドから返す必要があります。その後、ソースフィルターは開始時刻を (-1 ではなく) 指定してレート変更を設定できます。

ソースフィルターは、既にキューに入れられているレート変更よりも早い開始時刻のレート変更をスケジュールできます。この場合、キュー内のそれ以降のレート変更は無効になるため、デコーダーはそれらを破棄する必要があります。StartTime が -1 の場合、デコーダーは新しいレート変更をキューに入れる前に、保留中のすべてのレート変更を破棄する必要があります。

ソースフィルターは、過去の開始時刻、つまりキューに入っているどのサンプルよりも早い時刻に対してレート変更をスケジュールすることもできます。その場合、デコーダーはキューに入っているすべてのサンプルのタイムスタンプを調整する必要があります。

サンプルが開始時刻をまたいでおり、新しいレートに互換性がない場合の動作は未定義です。デコーダーはメディアに応じて、そのサンプルを保持することも破棄することもできます。

ソースフィルターの要件

デコーダーの要件

レート変更の計算

次の図では、出力タイムスタンプ (y) は次の式で与えられます。
         
         
         
         
         y = r(x - xi)

ここで x は入力タイムスタンプ、r はレート、xi は現在のレートに対する x 切片です。この式は、m を傾き (r)、b を y 切片として、点 xi における方程式 y = mx + b を解くことで得られます。これにより b = -m(xi) が得られ、これを方程式 y = mx + b に代入し直します。

入力タイムスタンプと出力タイムスタンプの関係を示す図。

デコーダーは、次のようにして x 切片を計算できます。ここで、

    r1 = 直前のレート

    r2 = 現在のレート

    xi1 = 直前のレート変更に対する x 切片

    xi2 = 現在のレート変更に対する x 切片

    x = 現在のレート変更の開始時刻

未知数 xi2 は、y = r2(x - xi2) = r1(x - xi1) と置いて xi2 について解くことで求められます (後続の図を参照してください)。その結果は次のとおりです。

    xi2 = (r1 / r2)(xi1 - x) + x

r2 の x 切片を示す図。

時刻 0 で再生が 1x である特別なケースでは、r1 = 1、xi1 = 0 となります。

次のコードは、最も先行するサンプルを起点としてレートを設定します。有効な開始時刻は prtStartTime パラメーターで返されます。


HRESULT SetRateToMostForward( 
    IKsPropertySet *pIKsPropertySet,
    double dRate,
    REFERENCE_TIME *prtStartTime  
    )
{
    AM_SimpleRateChange rateSet;
    rateSet.Rate        = LONG(dRate * 10000);
    rateSet.StartTime   = -1; //  Use the most forward sample

    HRESULT hr = pIKsPropertySet->Set(
        AM_KSPROPSETID_TSRateChange, //  Property set.
        AM_RATE_SimpleRateChange,    //  Property ID.
        NULL,                        //  Instance data.
        0,                           //  Size of instance data.
        &rateSet,                    //  Property data.
        sizeof(rateSet)              //  Size of property data.
        );
    if (SUCCEEDED(hr)) 
    {
        // Get the actual time.
        DWORD cbData = sizeof(REFERENCE_TIME);
        hr = pIKsPropertySet->Get (
            AM_KSPROPSETID_TSRateChange, //  Property set.
            AM_RATE_QueryLastRateSegPTS, //  Property ID.
            NULL,                        //  Instance data.
            0,                           //  Size of instance data.
            prtStartTime,                //  Property data.
            cbData,                      //  Size of property data.
            &cbData                      //  Size of data returned.
            );
    }
    return hr;
}

次のコードは、指定した時刻を起点としてレートを設定します。


HRESULT SetRate(
    IKsPropertySet *pIKsPropertySet,
    double dRate,
    REFERENCE_TIME rtStartTime
    )
{
    AM_SimpleRateChange rateSet ;

    rateSet.Rate        = LONG(dRate * 10000);
    rateSet.StartTime   = rtStartTime;

    return IKsPropertySet->Set(
        AM_KSPROPSETID_TSRateChange,    //  Property set.
        AM_RATE_SimpleRateChange,       //  Property ID.
        NULL,                           //  Instance data.
        0,                              //  Size of instance data.
        &rateSet,                       //  Property data.
        sizeof(RateSet)                 //  Size of property data.
        );
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での定義

#include <windows.h>

// AM_SimpleRateChange  (x64 16 / x86 16 バイト)
typedef struct AM_SimpleRateChange {
    LONGLONG StartTime;
    INT Rate;
} AM_SimpleRateChange;
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct AM_SimpleRateChange
{
    public long StartTime;
    public int Rate;
}
Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Public Structure AM_SimpleRateChange
    Public StartTime As Long
    Public Rate As Integer
End Structure
import ctypes
from ctypes import wintypes

class AM_SimpleRateChange(ctypes.Structure):
    _fields_ = [
        ("StartTime", ctypes.c_longlong),
        ("Rate", ctypes.c_int),
    ]
#[repr(C)]
pub struct AM_SimpleRateChange {
    pub StartTime: i64,
    pub Rate: i32,
}
import "golang.org/x/sys/windows"

type AM_SimpleRateChange struct {
	StartTime int64
	Rate int32
}
type
  AM_SimpleRateChange = record
    StartTime: Int64;
    Rate: Integer;
  end;
const AM_SimpleRateChange = extern struct {
    StartTime: i64,
    Rate: i32,
};
type
  AM_SimpleRateChange {.bycopy.} = object
    StartTime: int64
    Rate: int32
struct AM_SimpleRateChange
{
    long StartTime;
    int Rate;
}

HSP用 定義

HSP3.7/3.8 は構造体機能が無いため4byte整数配列(dim)+peek/poke で操作(32/64bitでサイズ・位置が異なる場合はタブで分割)。IronHSP は NSTRUCT(#defstruct/stdim/->)で32/64bit共通。

; HSP3.7/3.8 は構造体機能が無いため、4byte整数の配列変数で操作します。(x64 レイアウト)
; AM_SimpleRateChange サイズ: 16 バイト(x64)
dim st, 4    ; 4byte整数×4(構造体サイズ 16 / 4 切り上げ)
; StartTime : LONGLONG (+0, 8byte)  qpoke st,0,値 / qpeek(st,0)  ※IronHSPのみ。3.7/3.8は lpoke st,0,下位 : lpoke st,4,上位
; Rate : INT (+8, 4byte)  st.2 = 値  /  値 = st.2   (lpoke/lpeek も可)
; ※4byte境界の整数は添字 st.N(N=オフセット/4)で読み書き可。それ以外は peek/poke 系を使用。
; IronHSP は NSTRUCT(構造体)をサポート。32bit/64bit どちらでも同じコードで動作します。
#defstruct global AM_SimpleRateChange
    #field int64 StartTime
    #field int Rate
#endstruct

stdim st, AM_SimpleRateChange        ; NSTRUCT 変数を確保
st->StartTime = 100
mes "StartTime=" + st->StartTime