Пишу DirectX plug-in, наследуясь от CTransInPlaceFilter. Когда он встраивается в приложение (звуковой редактор), то редактор задаёт размер звукового буфера сам. Причём каждый редактор задаёт по-своему. Так как мне не зависить от этого и самому указывать размер буфера? Перерыл всю документацию и исходники к lib, по разному пробовал выставлять размер. Бесполезно.
Здравствуйте lavrov_alex, Вы писали:
LA>Пишу DirectX plug-in, наследуясь от CTransInPlaceFilter. Когда он встраивается в приложение (звуковой редактор), то редактор задаёт размер звукового буфера сам. Причём каждый редактор задаёт по-своему. Так как мне не зависить от этого и самому указывать размер буфера? Перерыл всю документацию и исходники к lib, по разному пробовал выставлять размер. Бесполезно.
Можно немного по конкретнее? какой звуковой буфер? приведи для ясность кусок кода твоего фильтра.
Здравствуйте 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;
}
Мой класс MyPlugIn наследуется от CTransInPlaceFilter, CPersistStream, ISpecifyPropertyPages и моего класса Filter, в котором реализовано, как обрабатывать звук. Я так понял по документации и т. д., что когда приложение (звуковой редактор) коннектит свой OutputPin к моему InputPin, то вызывает через IMemInputPin*, относящиийся к моему InputPin, GetAllocatorRequirements, затем GetAllocator, а затем по результатам делает DecideBufferSize. Поскольку GetAllocator определён в CTransInPlaceInputPin, то надо написать свой GetAllocatorRequirements и задать в нём свои ALLOCATOR_PROPERTIES. Для этого я пишу MyTransInPlaceInputPin:
class MyTransInPlaceInputPin : public CTransInPlaceInputPin{
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){
Здесь DbgLog выводит в файл, что я установил, поэтому я знаю,что этот код точно исполняется.
Когда начинается обработка звука в функции
HRESULT MyPlugIn::Transform(IMediaSample* pSample), то я тем же DbgLog вывожу
long int size_buf=pSample->GetActualDataLength(); Под этим значением я и понимаю размер буфера. И он равен в редакторе Cool Edit Pro 11024 для всех буферов. Для других редакторов другой размер, но он все равно не равен тому, что я выставил, т. е. 8192.
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-у, он выше твоего, я как там написано пробовал, но всё с таким же успехом.
[skiped ...]
А>И в итоге в функции Transform(IMediaSample* pSample) я имею pSample->GetActualDataLength()==11024; Это такой буфер выставляет редактор Cool Edit Pro, в других буфер другой, но не тот , кторый я выставил в DecideBufferSize (8192). Ещё посмотри мой ответ Lostar-у, он выше твоего, я как там написано пробовал, но всё с таким же успехом.
Вобщем и в целом все понятно.
Однако у тебя есть какие-нибудь веские причины по которым ты не можешь пользоваться тем буфером который реально выставляется?
Я еще гляну в исходники своего фильтра, может что-нибудь прояснится.
Тут ты выставил размер для выходного пина твоего фильтра.
А> 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-у, он выше твоего, я как там написано пробовал, но всё с таким же успехом.
Lostar, есть веские причины. Необходимо делать Фурье по числу точек 2^(целое число) (быстрый Фурье). А если Cool Edit Pro выставляет 11024, а для 2-канального, 2-байтового звука это на один канал будет только 11024/4==2756 samples, то во-первых Фурье>2048 не сделать, а во-вторых если сделать 2048, останется 2756-2048==708, куда их, в буфер свой засунуть? Возня начнётся, код будет кучу ошибок содержать. И вообще DirectShow — это отстойная либа, если буфер нельзя выставить. set_buffer в звуке — это как put_pixel в графике.
Здравствуйте 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 в графике.
Я не утверждаю что нельзя. Я не знаю как это сделать.
Может и отстойная, но мне вполне подходило. :о)
Здравствуйте lavrov_alex, Вы писали: LA>Возня начнётся, код будет кучу ошибок содержать...
Это от только от Вас, уважаемый, будет зависеть.
Могу на вскидку предложить еще такой путь: реализовать свой аллокатор,
который будет заводить буфер достаточно большого размера и отдавать его
по частям:
Таким образом, филтры думают, что работают с буфером маленького размера,
а когда байтиков накапливается достаточно много, бурутся n байт начиная
с позиции своего указателя (в своем буфере), указатель смещается и все довольны.
Если получится сделать его размером в наименьшее общее кратное, то даже не
придется заботится о "хвосте", а иначе придется копировать его в начало
и нарезать самплы от нового вмещения.