Как задать размер буфера в DirectShow?
От: lavrov_alex  
Дата: 28.02.02 05:32
Оценка:
Пишу DirectX plug-in, наследуясь от CTransInPlaceFilter. Когда он встраивается в приложение (звуковой редактор), то редактор задаёт размер звукового буфера сам. Причём каждый редактор задаёт по-своему. Так как мне не зависить от этого и самому указывать размер буфера? Перерыл всю документацию и исходники к lib, по разному пробовал выставлять размер. Бесполезно.
Re: Как задать размер буфера в DirectShow?
От: Lostar Россия  
Дата: 28.02.02 09:07
Оценка:
Здравствуйте lavrov_alex, Вы писали:

LA>Пишу DirectX plug-in, наследуясь от CTransInPlaceFilter. Когда он встраивается в приложение (звуковой редактор), то редактор задаёт размер звукового буфера сам. Причём каждый редактор задаёт по-своему. Так как мне не зависить от этого и самому указывать размер буфера? Перерыл всю документацию и исходники к lib, по разному пробовал выставлять размер. Бесполезно.


Можно немного по конкретнее? какой звуковой буфер? приведи для ясность кусок кода твоего фильтра.
С уважением, Николай.
Re: Как задать размер буфера в DirectShow?
От: Snax Россия  
Дата: 28.02.02 11:14
Оценка:
Здравствуйте lavrov_alex, Вы писали:

LA>Так как мне не зависить от этого и самому указывать размер буфера?


А как же основы демократии? А если другие фильтры не умеют работать с такими
большими/маленькими буферами? Не, ты кончно можешь предложить свой размер
буффера через DecideBufferSize, но будь готов к тому, что тебя никто не поддержит

HRESULT CMySuperPupperPhylter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties)
{
    CAutoLock cAutoLock(m_pFilter->pStateLock());

    ASSERT(pAlloc);
    ASSERT(pProperties);
    HRESULT hr;

    pProperties->cbBuffer = 1024*1024; // Мег!
    pProperties->cBuffers = 2; // Два буффера по мегу

    ALLOCATOR_PROPERTIES Actual;
    hr = pAlloc->SetProperties(pProperties,&Actual);
    if (FAILED(hr))
        return hr; // Что-то сломалось
    
    if (Actual.cbBuffer < pProperties->cbBuffer)
        return E_FAIL; // Не согласны. Вот ламеры!
   
    return S_OK;
}
Re[2]: Re: Как задать размер буфера в DirectShow?
От: lavrov_alex  
Дата: 01.03.02 04:06
Оценка:
Мой класс MyPlugIn наследуется от CTransInPlaceFilter, CPersistStream, ISpecifyPropertyPages и моего класса Filter, в котором реализовано, как обрабатывать звук. Я так понял по документации и т. д., что когда приложение (звуковой редактор) коннектит свой OutputPin к моему InputPin, то вызывает через IMemInputPin*, относящиийся к моему InputPin, GetAllocatorRequirements, затем GetAllocator, а затем по результатам делает DecideBufferSize. Поскольку GetAllocator определён в CTransInPlaceInputPin, то надо написать свой GetAllocatorRequirements и задать в нём свои ALLOCATOR_PROPERTIES. Для этого я пишу MyTransInPlaceInputPin:

class MyTransInPlaceInputPin : public CTransInPlaceInputPin{

public:

NXPlugInInputPin(char* pObjectName, CTransInPlaceFilter* pFilter, HRESULT* phr, wchar_t* pName) :
CTransInPlaceInputPin(pObjectName, pFilter, phr, pName){}

HRESULT __stdcall GetAllocatorRequirements(ALLOCATOR_PROPERTIES*);

};

Дальше добавляю в класс MyPlugIn
CBasePin* MyPlugIn::GetPin(int n){

HRESULT hr = S_OK;

// Create an input pin if not already done

if(!m_pInput){

m_pInput=new MyTransInPlaceInputPin(NAME("My input pin"), this, &hr, L"Input");
// Constructor for MyTransInPlaceInputPin can't fail
ASSERT(SUCCEEDED(hr));

}

// Create an output pin if not already done

if(m_pInput && !m_pOutput){

m_pOutput=new CTransInPlaceOutputPin(NAME("NXInPlace output pin"), this, &hr, L"Output");
// a failed return code should delete the object
ASSERT(SUCCEEDED(hr));

if(!m_pOutput){

delete m_pInput;
m_pInput=0;

}

}

ASSERT(n==0 || n==1);

// Return the appropriate pin

switch(n){

case 0:

return m_pInput;

case 1:

return m_pOutput;

default:

return 0;

}

}

Он практически содран из CTransInPlaceFilter::GetPin.
Далее пишу GetAllocatorRequirements
HRESULT __stdcall MyTransInPlaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES* pProps){

CCritSec Lock; //Это надо?
CAutoLock foo(&Lock);

ALLOCATOR_PROPERTIES request={1, 8192, 1, 0};
*pProps=request;

DbgLog((LOG_TRACE, 2, TEXT("my allocator props %d,%d,%d,%d"), request.cBuffers, request.cbBuffer, request.cbAlign, request.cbPrefix));

return S_OK;
}

Здесь DbgLog выводит в файл, что я установил, поэтому я знаю,что этот код точно исполняется.

Когда начинается обработка звука в функции
HRESULT MyPlugIn::Transform(IMediaSample* pSample), то я тем же DbgLog вывожу
long int size_buf=pSample->GetActualDataLength(); Под этим значением я и понимаю размер буфера. И он равен в редакторе Cool Edit Pro 11024 для всех буферов. Для других редакторов другой размер, но он все равно не равен тому, что я выставил, т. е. 8192.

Ну так и что делать?!!
Re[2]: Как задать размер буфера в DirectShow?
От: Аноним  
Дата: 01.03.02 04:44
Оценка:
Snax, я так пробовал:

HRESULT MyPlugIn::DecideBufferSize (IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProp){

HRESULT hr;

DbgLog((LOG_TRACE, 2, TEXT("DecideBufferSize")));

DbgLog((LOG_TRACE, 2, TEXT("Default Allocator props %d,%d,%d,%d"), pProp->cBuffers, pProp->cbBuffer, pProp->cbAlign, pProp->cbPrefix)); //выдаёт {0, 0, 1, 0}

ALLOCATOR_PROPERTIES required, actual;
required.cBuffers=1;
required.cbBuffer=8192;
required.cbAlign=1;
required.cbPrefix=0;
hr=pAlloc->SetProperties(&required, &actual);

if(hr>=0){

*pProp=actual;
DbgLog((LOG_TRACE, 2, TEXT("actual Allocator props %d,%d,%d,%d"), pProp->cBuffers, pProp->cbBuffer, pProp->cbAlign, pProp->cbPrefix)); //выдаёт {1, 8192, 1, 0}

}

else{
DbgLog((LOG_TRACE, 2, TEXT("pAlloc->SetProperties() FAILED=%.08lXh"), hr));
return E_FAIL;
}

ALLOCATOR_PROPERTIES in, out;

InputPin()->PeekAllocator()->GetProperties(&in);
OutputPin()->PeekAllocator()->GetProperties(&out);

DbgLog((LOG_TRACE, 2, TEXT("in my decide Allocator props %d,%d,%d,%d"), in.cBuffers, in.cbBuffer, in.cbAlign, in.cbPrefix)); //выдаёт {1, 11024, 1 ,0}
DbgLog((LOG_TRACE, 2, TEXT("out my decide Allocator props %d,%d,%d,%d"), out.cBuffers, out.cbBuffer, out.cbAlign, out.cbPrefix)); //выдаёт {1, 8192, 1 ,0}
//Такая фигня с CTransInPlaceFilter, который вроде как должен одну память под Input
//and Output Pin пользовать.
return hr;
}

И в итоге в функции Transform(IMediaSample* pSample) я имею pSample->GetActualDataLength()==11024; Это такой буфер выставляет редактор Cool Edit Pro, в других буфер другой, но не тот , кторый я выставил в DecideBufferSize (8192). Ещё посмотри мой ответ Lostar-у, он выше твоего, я как там написано пробовал, но всё с таким же успехом.
Re[3]: Как задать размер буфера в DirectShow?
От: Lostar Россия  
Дата: 01.03.02 09:10
Оценка:
Здравствуйте Аноним, Вы писали:

[skiped ...]

А>И в итоге в функции Transform(IMediaSample* pSample) я имею pSample->GetActualDataLength()==11024; Это такой буфер выставляет редактор Cool Edit Pro, в других буфер другой, но не тот , кторый я выставил в DecideBufferSize (8192). Ещё посмотри мой ответ Lostar-у, он выше твоего, я как там написано пробовал, но всё с таким же успехом.


Вобщем и в целом все понятно.
Однако у тебя есть какие-нибудь веские причины по которым ты не можешь пользоваться тем буфером который реально выставляется?
Я еще гляну в исходники своего фильтра, может что-нибудь прояснится.
С уважением, Николай.
Re[3]: Как задать размер буфера в DirectShow?
От: Lostar Россия  
Дата: 01.03.02 10:16
Оценка:
Здравствуйте Аноним, Вы писали:

А>Snax, я так пробовал:


А>HRESULT MyPlugIn::DecideBufferSize (IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProp){


А> HRESULT hr;


А> DbgLog((LOG_TRACE, 2, TEXT("DecideBufferSize")));


А> DbgLog((LOG_TRACE, 2, TEXT("Default Allocator props %d,%d,%d,%d"), pProp->cBuffers, pProp->cbBuffer, pProp->cbAlign, pProp->cbPrefix)); //выдаёт {0, 0, 1, 0}


А> ALLOCATOR_PROPERTIES required, actual;

А> required.cBuffers=1;
А> required.cbBuffer=8192;
А> required.cbAlign=1;
А> required.cbPrefix=0;
А> hr=pAlloc->SetProperties(&required, &actual);

А> if(hr>=0){


А> *pProp=actual;

А> DbgLog((LOG_TRACE, 2, TEXT("actual Allocator props %d,%d,%d,%d"), pProp->cBuffers, pProp->cbBuffer, pProp->cbAlign, pProp->cbPrefix)); //выдаёт {1, 8192, 1, 0}

А> }


Тут ты выставил размер для выходного пина твоего фильтра.

А> else{

А> DbgLog((LOG_TRACE, 2, TEXT("pAlloc->SetProperties() FAILED=%.08lXh"), hr));
А> return E_FAIL;
А> }

А> ALLOCATOR_PROPERTIES in, out;


А> InputPin()->PeekAllocator()->GetProperties(&in);

А> OutputPin()->PeekAllocator()->GetProperties(&out);

А> DbgLog((LOG_TRACE, 2, TEXT("in my decide Allocator props %d,%d,%d,%d"), in.cBuffers, in.cbBuffer, in.cbAlign, in.cbPrefix)); //выдаёт {1, 11024, 1 ,0}

А> DbgLog((LOG_TRACE, 2, TEXT("out my decide Allocator props %d,%d,%d,%d"), out.cBuffers, out.cbBuffer, out.cbAlign, out.cbPrefix)); //выдаёт {1, 8192, 1 ,0}
А> //Такая фигня с CTransInPlaceFilter, который вроде как должен одну память под Input
А> //and Output Pin пользовать.
А>return hr;
А>}
Получается, что у тебя размер входного буфера(который затребовал вышестоящий фильтр от твоего, что есть по моему правильно) отличается от размера выходного(который ты задаешь и который будет использовать нижестоящий фильтр) по всей видимости InPlace фильтр не может работать с одним буффером когда входные данные отличаются от выходных по размеру, либо он будет работать не корректно.

Вобщем как и сказал Snax(и я полностью с ним соглашаюсь) ты могешь задать размер только для OutPin, что есть верно.
вобщем то и в хелпе так написанно: DecideBufferSize и GetAllocatorRequirements необходимы только для выходных пинов.

А>И в итоге в функции Transform(IMediaSample* pSample) я имею pSample->GetActualDataLength()==11024; Это такой буфер выставляет редактор Cool Edit Pro, в других буфер другой, но не тот , кторый я выставил в DecideBufferSize (8192). Ещё посмотри мой ответ Lostar-у, он выше твоего, я как там написано пробовал, но всё с таким же успехом.
С уважением, Николай.
Re[4]: Как задать размер буфера в DirectShow?
От: lavrov_alex  
Дата: 01.03.02 10:36
Оценка:
Lostar, есть веские причины. Необходимо делать Фурье по числу точек 2^(целое число) (быстрый Фурье). А если Cool Edit Pro выставляет 11024, а для 2-канального, 2-байтового звука это на один канал будет только 11024/4==2756 samples, то во-первых Фурье>2048 не сделать, а во-вторых если сделать 2048, останется 2756-2048==708, куда их, в буфер свой засунуть? Возня начнётся, код будет кучу ошибок содержать. И вообще DirectShow — это отстойная либа, если буфер нельзя выставить. set_buffer в звуке — это как put_pixel в графике.
Re[5]: Как задать размер буфера в DirectShow?
От: Lostar Россия  
Дата: 01.03.02 10:57
Оценка:
Здравствуйте lavrov_alex, Вы писали:

LA>Lostar, есть веские причины. Необходимо делать Фурье по числу точек 2^(целое число) (быстрый Фурье). А если Cool Edit Pro выставляет 11024, а для 2-канального, 2-байтового звука это на один канал будет только 11024/4==2756 samples, то во-первых Фурье>2048 не сделать, а во-вторых если сделать 2048, останется 2756-2048==708, куда их, в буфер свой засунуть? Возня начнётся, код будет кучу ошибок содержать.

И вообще DirectShow — это отстойная либа, если буфер нельзя выставить. set_buffer в звуке — это как put_pixel в графике.
Я не утверждаю что нельзя. Я не знаю как это сделать.
Может и отстойная, но мне вполне подходило. :о)
С уважением, Николай.
Re[5]: Как задать размер буфера в DirectShow?
От: Snax Россия  
Дата: 01.03.02 11:23
Оценка:
Здравствуйте lavrov_alex, Вы писали:
LA>Возня начнётся, код будет кучу ошибок содержать...
Это от только от Вас, уважаемый, будет зависеть.
Могу на вскидку предложить еще такой путь: реализовать свой аллокатор,
который будет заводить буфер достаточно большого размера и отдавать его
по частям:

------Буфер-----------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 ....
----------------------------
^ внутренний указатель где-то тут.

Таким образом, филтры думают, что работают с буфером маленького размера,
а когда байтиков накапливается достаточно много, бурутся n байт начиная
с позиции своего указателя (в своем буфере), указатель смещается и все довольны.
Если получится сделать его размером в наименьшее общее кратное, то даже не
придется заботится о "хвосте", а иначе придется копировать его в начало
и нарезать самплы от нового вмещения.

Не так много возьни, как может показаться.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.