Очень медленное чтение IMediaSample в transform фильтре
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 04.09.07 09:15
Оценка:
В фильтре необходимо работать с данными получаемыми как

transform(IMediaSample* aSample)
{
hr = aSample->GetPointer(&origBuffer);


memcopy этого буфера занимает 20!!! миллисекунд, что катастрофически долго, насколько я понял вся проблема что он лежит где то в видеопамяти которая быстро пишется но медленно читается, нельзя ли его оттуда какой то функцией все таки быстро скопировать?

заранее спасибо
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re: Очень медленное чтение IMediaSample в transform фильтре
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 05.09.07 07:09
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>В фильтре необходимо работать с данными получаемыми как


AS>transform(IMediaSample* aSample)

AS>{
AS>hr = aSample->GetPointer(&origBuffer);

Попробуйте написать не TransInPlace, а Transform фильтр. Вы получите лишнее копирование и проблемы с динамическим измнением формата, зато избавитесь от чтения из видеопамяти.

Второй вариант -- не используйте VMR и выводите изображение через старый Video Renderer.
Re: Очень медленное чтение IMediaSample в transform фильтре
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 05.09.07 10:02
Оценка:
А как примерно граф выглядит? Интересно, как данные в видеопамять попали.
Re[2]: Очень медленное чтение IMediaSample в transform фильт
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 05.09.07 13:21
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>А как примерно граф выглядит? Интересно, как данные в видеопамять попали.



граф — сейчас из .avi файла читает через кодек divx идет видео (в будущем будет идти из карты видеозахвата)
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[2]: Очень медленное чтение IMediaSample в transform фильт
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 05.09.07 13:22
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Здравствуйте, Aleksey Skurihin, Вы писали:


AS>>В фильтре необходимо работать с данными получаемыми как


AS>>transform(IMediaSample* aSample)

AS>>{
AS>>hr = aSample->GetPointer(&origBuffer);

ДМ>Попробуйте написать не TransInPlace, а Transform фильтр. Вы получите лишнее копирование и проблемы с динамическим измнением формата, зато избавитесь от чтения из видеопамяти.


вообще я так думал что у меня и есть transform фильтр, а в чем разница?



ДМ>Второй вариант -- не используйте VMR и выводите изображение через старый Video Renderer.


ага сенкс, а почему так?
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[3]: Очень медленное чтение IMediaSample в transform фильт
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 06.09.07 08:01
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>вообще я так думал что у меня и есть transform фильтр, а в чем разница?


Разница в том что TransInPlace фильтр обычно не использует свои аллокаторы, а соеденяет аллокаторы вышележащего и нижележащего фильтров. VMR предоставляет аллокатор на видеопамяти, поэтому чтение из неё получается медленным.

Общий совет -- никогда не читать данные из выходного сэмпла, только писать.

ДМ>>Второй вариант -- не используйте VMR и выводите изображение через старый Video Renderer.


Video Renderer использует обычный GDI, а VMR работает напрямую с видеопамятью.
Re[2]: Очень медленное чтение IMediaSample в transform фильт
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 06.09.07 08:03
Оценка:
Здравствуйте, D. Mon, Вы писали:

DM>А как примерно граф выглядит? Интересно, как данные в видеопамять попали.


Запросто, если обсуждаемый фильтр TransInPlace, а рендерер -- VMR.
VMR строит свои аллокаторы непосредственно на поверхностях видеопамяти, при удачном стечении обстоятельств внутри выходного сэмпла может оказаться указатель на участок видеопамяти.
Re[4]: Очень медленное чтение IMediaSample в transform фильт
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 06.09.07 08:53
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Здравствуйте, Aleksey Skurihin, Вы писали:


AS>>вообще я так думал что у меня и есть transform фильтр, а в чем разница?


ДМ>Разница в том что TransInPlace фильтр обычно не использует свои аллокаторы, а соеденяет аллокаторы вышележащего и нижележащего фильтров. VMR предоставляет аллокатор на видеопамяти, поэтому чтение из неё получается медленным.


ага спасибо буду думать. Т.е в моем случае DivX пишет в аллокатор данный VMR, а я читаю? а надо сделать чтоб DivX писал куда то внутрь меня, а я сам потом писал уже в аллокатор VMR?

ДМ>Общий совет -- никогда не читать данные из выходного сэмпла, только писать.



Так мне нужно обрабатывать данные... я анализирую каждый кадр видео и ищу на нем заданные обьекты, при этом данные на моем входном пине медленные (поступают они от декодера DivX)

ДМ>>>Второй вариант -- не используйте VMR и выводите изображение через старый Video Renderer.


ДМ>Video Renderer использует обычный GDI, а VMR работает напрямую с видеопамятью.


ага

а можно использовать какое то поблочное копирование через DMA чтобы быстро перенести из видеопамяти в основную? И если можно то как? Пока ничего не нашел.
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[5]: Очень медленное чтение IMediaSample в transform фильт
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 06.09.07 09:11
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>ага спасибо буду думать. Т.е в моем случае DivX пишет в аллокатор данный VMR, а я читаю? а надо сделать чтоб DivX писал куда то внутрь меня, а я сам потом писал уже в аллокатор VMR?


Да. Это нормальный режим работы. Если вы вставляете TransInPlace фильтр и анализируете содержимое буффера, то неявно производите чтение из видеопамяти. Решение -- использование Transform фильтра. Можно так же попробовать указать параметр bModifiesData = true в конструкторе CTransInPlaceFilter.

AS>а можно использовать какое то поблочное копирование через DMA чтобы быстро перенести из видеопамяти в основную? И если можно то как? Пока ничего не нашел.


Не знаю, скорее всего нет.
Re[5]: Очень медленное чтение IMediaSample в transform фильт
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 06.09.07 11:06
Оценка:
AS>а можно использовать какое то поблочное копирование через DMA чтобы быстро перенести из видеопамяти в основную?

Нет смысла. Лучше сделать как посоветовали с Transform — выдавать DivX'у свой аллокатор в обычной памяти. Тогда чтения из видеопамяти не понадобится вообще, только запись.
Re[2]: Очень медленное чтение IMediaSample в transform фильт
От: Wifer http://gamedev.by
Дата: 06.09.07 12:52
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Здравствуйте, Aleksey Skurihin, Вы писали:


AS>>В фильтре необходимо работать с данными получаемыми как


AS>>transform(IMediaSample* aSample)

AS>>{
AS>>hr = aSample->GetPointer(&origBuffer);

ДМ>Попробуйте написать не TransInPlace, а Transform фильтр. Вы получите лишнее копирование и проблемы с динамическим измнением формата, зато избавитесь от чтения из видеопамяти.


ДМ>Второй вариант -- не используйте VMR и выводите изображение через старый Video Renderer.


Это зависит от вида сорса, и то несильно, не должны данные хранится в видеопямяти )

Ну проблема я думаю не в том, что что-либо лежит в видео памяти, в логике проблемы, ты опиши что за фильтр и пре пост фильтры которые используеш, вид синхронизации, используемый сорс, ну и смысл использования твоего трансинплейс фильтра
... << RSDN@Home 1.2.0 alpha rev. 685>>
Re[6]: Очень медленное чтение IMediaSample в transform фильт
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 06.09.07 12:56
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Здравствуйте, Aleksey Skurihin, Вы писали:


AS>>ага спасибо буду думать. Т.е в моем случае DivX пишет в аллокатор данный VMR, а я читаю? а надо сделать чтоб DivX писал куда то внутрь меня, а я сам потом писал уже в аллокатор VMR?


ДМ>Да. Это нормальный режим работы. Если вы вставляете TransInPlace фильтр и анализируете содержимое буффера, то неявно производите чтение из видеопамяти. Решение -- использование Transform фильтра.


А можете дать ссылку или исходники простенького правильного аллокатора? Что оно такое и с чем едят. А то погряз совсем, как обычно полно работы, а тут у человека проблемы, пришлось срочно его заменить (мной), выручайте кто может.

Можно так же попробовать указать параметр bModifiesData = true в конструкторе CTransInPlaceFilter.

У меня все от IBaseFIlter наследуется, тут куча чужих исходников сижу разбираюсь. Но такого флага не вижу.

Всем спасибо
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[3]: Очень медленное чтение IMediaSample в transform фильт
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 06.09.07 12:59
Оценка:
W>Это зависит от вида сорса, и то несильно, не должны данные хранится в видеопямяти )

W>Ну проблема я думаю не в том, что что-либо лежит в видео памяти, в логике проблемы, ты опиши что за фильтр и пре пост фильтры которые используеш, вид синхронизации, используемый сорс, ну и смысл использования твоего трансинплейс фильтра



видео — сплиттер — divx — myFilter — vmr9

мой фильтр анализирует изображения
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[7]: Очень медленное чтение IMediaSample в transform фильт
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 07.09.07 07:03
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>А можете дать ссылку или исходники простенького правильного аллокатора? Что оно такое и с чем едят. А то погряз совсем, как обычно полно работы, а тут у человека проблемы, пришлось срочно его заменить (мной), выручайте кто может.


А чем стандартные аллокаторы не устраивают? Вам нужно подключится к VMR? VMR допускает соедениее только при условии использования своего аллокатора, в противном случае соеденение отвергается. Выбор аллокатора производится в методе CBaseOutputPin::DecideAllocator.

Но VMR также требует динамического изменения формата, описание действия здесь http://msdn2.microsoft.com/en-us/library/ms867156.aspx#dynformat_queryacceptupstream


AS>У меня все от IBaseFIlter наследуется, тут куча чужих исходников сижу разбираюсь. Но такого флага не вижу.


Конечно не наблюдаете, это перемнная класса CTransInPlaceFilter
Re[4]: Очень медленное чтение IMediaSample в transform фильт
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 07.09.07 07:06
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>видео — сплиттер — divx — myFilter — vmr9


AS>мой фильтр анализирует изображения


Обычная задача для Transform фильтра, только поддержку динаммческого измнения формата придётся написать, без неё VMR не подключается.
Re[8]: Очень медленное чтение IMediaSample в transform фильт
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 07.09.07 09:17
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Здравствуйте, Aleksey Skurihin, Вы писали:


AS>>А можете дать ссылку или исходники простенького правильного аллокатора? Что оно такое и с чем едят. А то погряз совсем, как обычно полно работы, а тут у человека проблемы, пришлось срочно его заменить (мной), выручайте кто может.


ДМ>А чем стандартные аллокаторы не устраивают? Вам нужно подключится к VMR? VMR допускает соедениее только при условии использования своего аллокатора, в противном случае соеденение отвергается. Выбор аллокатора производится в методе CBaseOutputPin::DecideAllocator.


А откуда мне взять аллоктаор который требует DivX?


И вопрос кто вызывает функцию receive входного пина? Я смотрю в примерах функция трансформ T CMyTransform::Transform(
IMediaSample *pSource, IMediaSample *pDest) принимает два медиасемпла, а у меня только один, откуда мне взять второй?
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[9]: Очень медленное чтение IMediaSample в transform фильт
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 07.09.07 10:13
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>А откуда мне взять аллоктаор который требует DivX?


Базовые реализации пинов (СBaseInputPin, CBaseOutputPin, CTransformInputPin, CTransformOutputPin) уже имеют всю необходимую поддержку для аллокторов. Если эта реализация вас не устраивает, можете воспотзоваться классом CMemAllocator.


AS>И вопрос кто вызывает функцию receive входного пина? Я смотрю в примерах функция трансформ T CMyTransform::Transform(

AS> IMediaSample *pSource, IMediaSample *pDest) принимает два медиасемпла, а у меня только один, откуда мне взять второй?

Вы должны самостотельно скорировать данные из входного медисэмпла в выходной. В этом суть transform фильра. Наряду с копированием можно произвести весь требуемый анализ.
Re[10]: Очень медленное чтение IMediaSample в transform филь
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 07.09.07 10:14
Оценка:
Вдогонку. Посмотрите пример EzRGB
Re[11]: Очень медленное чтение IMediaSample в transform филь
От: Aleksey Skurihin Украина http://www.adept7.kiev.ua
Дата: 07.09.07 14:27
Оценка:
Здравствуйте, Денис Майдыковский, Вы писали:

ДМ>Вдогонку. Посмотрите пример EzRGB


Спасибо я смотрел пример Contrast и на реализацию базовых классов, сейчас в итоге у меня такая вот проблема

видео идет но раз в 100 быстрее чем надо и вверх ногами
код копирования полностью по аналогии с примером написал


HRESULT
Filter::receive(IMediaSample* aSample)
{
    HRESULT hr;
    AM_SAMPLE2_PROPERTIES* props;
    IMemInputPin*    outputMemPin;

    props = inputPin_.getProperties();
    if (AM_STREAM_MEDIA != props->dwStreamId){
        outputMemPin = outputPin_.getMemInputPin();
        outputMemPin->Receive(aSample);
    }

    IMediaSample * outSample;
    if (outputPin_.isConnected()) {
        hr = initializeOutputSample(aSample, &outSample);
        if (FAILED(hr)) {
            return hr;
        }
        //hr = transform(aSample, outSample);
        hr = copySample(aSample, outSample);
        if (SUCCEEDED(hr)) {
            outputPin_.deliver(outSample);
                outSample->Release();
        }
    }
    outSample->Release();

    return NOERROR;
}



HRESULT
Filter::copySample(IMediaSample* aSampleIn,
                      IMediaSample* aSampleOut)
{
    //CheckPointer(aSampleIn,E_POINTER);
    //CheckPointer(aSampleOut,E_POINTER);

    // Copy the sample data
    BYTE *sourceBuffer, *destBuffer;
    long sourceSize = aSampleIn->GetActualDataLength();

    aSampleIn->GetPointer(&sourceBuffer);
    aSampleOut->GetPointer(&destBuffer);

    CopyMemory((PVOID) destBuffer,(PVOID) sourceBuffer, sourceSize);

    // Copy the sample times

    REFERENCE_TIME TimeStart, TimeEnd;
    if(NOERROR == aSampleIn->GetTime(&TimeStart, &TimeEnd))
    {
        aSampleOut->SetTime(&TimeStart, &TimeEnd);
    }

    LONGLONG MediaStart, MediaEnd;
    if(aSampleIn->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)
    {
        aSampleOut->SetMediaTime(&MediaStart,&MediaEnd);
    }

    // Copy the Sync point property

    HRESULT hr = aSampleIn->IsSyncPoint();
    if(hr == S_OK)
    {
        aSampleOut->SetSyncPoint(TRUE);
    }
    else if(hr == S_FALSE)
    {
        aSampleOut->SetSyncPoint(FALSE);
    }
    else
    {  // an unexpected error has occured...
        return E_UNEXPECTED;
    }

    // Copy the media type

    AM_MEDIA_TYPE *pMediaType;
    aSampleIn->GetMediaType(&pMediaType);
    aSampleOut->SetMediaType(pMediaType);
    FBCDeleteType(pMediaType);

    // Copy the preroll property

    hr = aSampleIn->IsPreroll();
    if(hr == S_OK)
    {
        aSampleOut->SetPreroll(TRUE);
    }
    else if(hr == S_FALSE)
    {
        aSampleOut->SetPreroll(FALSE);
    }
    else
    {  // an unexpected error has occured...
        return E_UNEXPECTED;
    }

    // Copy the discontinuity property

    hr = aSampleIn->IsDiscontinuity();

    if(hr == S_OK)
    {
        aSampleOut->SetDiscontinuity(TRUE);
    }
    else if(hr == S_FALSE)
    {
        aSampleOut->SetDiscontinuity(FALSE);
    }
    else
    {  // an unexpected error has occured...
        return E_UNEXPECTED;
    }

    // Copy the actual data length

    long lDataLength = aSampleIn->GetActualDataLength();
    aSampleOut->SetActualDataLength(lDataLength);

    return NOERROR;
}




HRESULT
Filter::initializeOutputSample(IMediaSample *aSample, IMediaSample **aOutSamplePtr)
{
    IMediaSample *outSample;

    AM_SAMPLE2_PROPERTIES* props;
    props = inputPin_.getProperties();
    
     DWORD flags = sample_skipped_ ? AM_GBF_PREVFRAMESKIPPED : 0;

     if (!(props->dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) {
         flags |= AM_GBF_NOTASYNCPOINT;
     }
 
    IMemAllocator* outputAllocator;
    outputAllocator = outputPin_.peekAllocator();
     if (!outputAllocator)
        return S_FALSE;

     HRESULT hr =outputAllocator->GetBuffer(&outSample,
                                            props->dwSampleFlags & AM_SAMPLE_TIMEVALID ? 
                                            &props->tStart : NULL, 
                                            props->dwSampleFlags & AM_SAMPLE_STOPVALID ? 
                                            &props->tStop : NULL, 
                                            flags);
     *aOutSamplePtr = outSample;
     if (FAILED(hr)) {
         return hr;
     }
    if (!outSample)
        return S_FALSE;

     IMediaSample2 *outSample2;
     if (SUCCEEDED(outSample->QueryInterface(IID_IMediaSample2,
                                             (void **)&outSample2))) {
        AM_SAMPLE2_PROPERTIES outProps;
         if FAILED(outSample2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES,
                                            tStart), (PBYTE)&outProps)) {
            return S_FALSE;
        }

        outProps.dwTypeSpecificFlags = props->dwTypeSpecificFlags;
        outProps.dwSampleFlags = (outProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) |
                                 (outProps.dwSampleFlags & ~AM_SAMPLE_TYPECHANGED);
        outProps.tStart = props->tStart;
        outProps.tStop  = props->tStop;
        outProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId);
        hr = outSample2->SetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId),
                                       (PBYTE)&outProps);
         if (props->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
             sample_skipped_ = FALSE;
         }
         outSample2->Release();
     } else {
         if (props->dwSampleFlags & AM_SAMPLE_TIMEVALID) {
             outSample->SetTime(&props->tStart,
                                &props->tStop);
         }
         if (props->dwSampleFlags & AM_SAMPLE_SPLICEPOINT) {
             outSample->SetSyncPoint(TRUE);
         }
        if (props->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
             outSample->SetDiscontinuity(TRUE);
             sample_skipped_ = FALSE;
         }
         // Copy the media times
 
         LONGLONG mediaStart, mediaEnd;
         if (aSample->GetMediaTime(&mediaStart, &mediaEnd) == NOERROR) {
             outSample->SetMediaTime(&mediaStart, &mediaEnd);
         }
    }
    return S_OK;
}
Радость от нахождения ошибки часто омрачаеться осознанием собственой глупости.
Re[12]: Очень медленное чтение IMediaSample в transform филь
От: Денис Майдыковский Россия http://www.maydyk.com
Дата: 10.09.07 07:19
Оценка:
Здравствуйте, Aleksey Skurihin, Вы писали:

AS>видео идет но раз в 100 быстрее чем надо и вверх ногами


Про "вверх ногами" надо самостоятельно обрабаотывать динамическое измненение формата. В примере этого нет. Описание здесь http://msdn2.microsoft.com/en-us/library/ms867156.aspx#dynformat_queryacceptupstream Увы, простым копированием данных не обойтись, придётся делать анализ ориентации DIB-ов и в некоторых случаях выполнять построчное копирование.

По скорость. Смотрите что с временами. Обратитите внимание что IMediaSample::GetTime() может вернуть значение VFW_S_NO_STOP_TIME, это значит что время старта сэмпла всё-же нужно установить.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.