Flash ActiveX: ¿Cómo cargar una película desde la memoria, un recurso o una transmisión?

StackOverflow https://stackoverflow.com/questions/423166

Pregunta

Estoy incorporando un control ActiveX de Flash en mi aplicación C ++ (Flash.ocx, Flash10a.ocx, etc., dependiendo de su versión de Flash).

Puedo cargar un archivo SWF llamando a LoadMovie (0, filename), pero el archivo debe residir físicamente en el disco. ¿Cómo cargar el SWF desde la memoria (o recurso, o flujo)? Estoy seguro de que debe haber una manera, porque las soluciones comerciales como la característica de f-in-box Cargar películas flash directamente desde la memoria también usa el control ActiveX de Flash.

¿Fue útil?

Solución

Aparentemente, tendré que proporcionar detalles para una votación "arriba" ... OK.

El búfer interno de flash cuando se inicia por primera vez indica si una película está cargada o si el búfer contiene propiedades en el búfer primero cuatro bytes.

gUfU - no hay película cargada. propiedades a seguir ....

fUfU - .. [4bytes] tamaño como entero.

luego la película DESCOMPRIMIDA o SWF como si fueran. Escribe una clase de IStream. llenar con lo anterior. guardar como szFile

TFlashStream *fStream = new TFlashStream(szFile);
// QI flash player

IPersistStreamInit * psStreamInit = 0;
shock->QueryInterface(::IID_IPersistStreamInit,  
                     (LPVOID*)&psStreamInit);
if(psStreamInit)
{
    psStreamInit->InitNew();
    psStreamInit->Load(fStream);
    psStreamInit->Release();
}
delete fStream;

Cosas a tener en cuenta: Cuando psStreamInit- > Load (fStream); llamará a IStream :: Read buscando el encabezado 'fUfU'.

si la devolución es correcta, psStreamInit llama a IStream :: Read para obtener el tamaño del búfer.

Si todo se ve bien hasta ahora, psStreamInit luego lee en fragmentos de 1024 bytes hasta que se agota la lectura. Sin embargo. para el encabezado y el tamaño del archivo.

STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead)

pcbRead no es válido. es posible que desee utilizar algo como IsBadReadPtr

-

Michael

Otros consejos

Para ahorrarte algo de escritura. Funciona para mí de esta manera (solo funciona no ampliamente probado):

void flash_load_memory(FlashWidget* w, void* data, ULONG size) {
        FlashMemoryStream fStream = FlashMemoryStream(data, size);
        IPersistStreamInit* psStreamInit = NULL;
        w->mFlashInterface->QueryInterface(IID_IPersistStreamInit,(LPVOID*) &psStreamInit);
        if(psStreamInit) {
            psStreamInit->InitNew();
            psStreamInit->Load((LPSTREAM)&fStream);
            psStreamInit->Release();
        }
    }

class FlashMemoryStream : IStream {
    public:
        FlashMemoryStream(void* data,ULONG size) {
            this->data = data;
            this->size = size;
            this->pos = 0;
        }

        HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppv) {
            return E_NOTIMPL;
        }

        ULONG STDMETHODCALLTYPE AddRef() {  
            return E_NOTIMPL;
        }

        ULONG STDMETHODCALLTYPE Release() {  
            return E_NOTIMPL;
        }

        // IStream methods
        STDMETHOD(Read) (void *pv,ULONG cb,ULONG *pcbRead) {
            if(pos == 0 && cb == 4) {
                memcpy(pv,"fUfU",4);
                pos += 4;
                return S_OK;
            }
            else if(pos == 4 && cb == 4) {
                memcpy(pv,&size,4);
                size += 8;
                pos += 4;
                return S_OK;
            }
            else {
                if(pos + cb > size) cb = size - pos;
                if(cb == 0) return S_FALSE;
                memcpy(pv,(char*)data + pos - 8,cb);
                if(pcbRead) (*pcbRead) = cb;
                pos += cb;
                return S_OK;
            }
        }

        STDMETHOD(Write) (void const *pv,ULONG cb,ULONG *pcbWritten) { return E_NOTIMPL; }
        STDMETHOD(Seek) (LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) { return E_NOTIMPL; }
        STDMETHOD(SetSize) (ULARGE_INTEGER libNewSize) { return E_NOTIMPL; }
        STDMETHOD(CopyTo) (IStream *pstm,ULARGE_INTEGER cb,ULARGE_INTEGER *pcbRead,ULARGE_INTEGER *pcbWritten) { return E_NOTIMPL; }
        STDMETHOD(Commit) (DWORD grfCommitFlags) { return E_NOTIMPL; }
        STDMETHOD(Revert) (void) { return E_NOTIMPL; }
        STDMETHOD(LockRegion) (ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType) { return E_NOTIMPL; }
        STDMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType) { return E_NOTIMPL; }
        STDMETHOD(Stat) (STATSTG *pstatstg,DWORD grfStatFlag) { return E_NOTIMPL; }
        STDMETHOD(Clone) (IStream **ppstm) { return E_NOTIMPL; }

        void* data;
        ULONG size;
        ULONG pos;
    };

Al ser un chico flash, no conozco ningún detalle en el lado C ++, pero si realizaste una solicitud en el lado Flash a un protocolo falso, en el lado C puedes interceptar esa solicitud y responderla con un flujo de datos ? Me refiero a algo como:

var mc:MovieClip = createEmptyMovieClip( "mc", 0 );
mc.loadMovie( "fakeprotocol://"+filename )

Siempre que la respuesta se vea (a Flash) como un flujo HTTP, debería funcionar. (Le pedimos disculpas por adelantado si " intercepta la solicitud y devuelve un flujo de datos " es la parte con la que solicita ayuda)

además .... Flash Player promueve el almacenamiento de IPersist. flash.QI IPersistStorage pStorage.load (mystorage_as_stream)

.. en teoría.

Lo siento por lo de arriba .. Tenía la intención de publicar Flash Player promueve IPersistStreamInit. flash.QI IPersistStreamInit pStream.load (my_stream)

Michael

¡Este método no funciona cuando intentas cargar una película a través del MovieclipLoader o LoadMovie desde otra película!

¡El resultado es reemplazar el archivo SWF de llamada! ... así que este método solo funciona para cargar el archivo base.

¿Alguien sabe un método mejor que funcione también con MovieClipLoader y LoadMovie? Gracias.

Ejemplo de MS VC ATL (se ha creado con VS 2010 SP1 + Windows SDK 7.1 y probado en Windows 7 SP1 de 64 bits con Flash64_11_3_300_257.ocx / Flash32_11_3_300_257.ocx y en Windows XP SP3 de 32 bits con Flash32_11_3_300_257.ocx):

#pragma pack(push, 1)

typedef struct _FLASH_STREAM_HEADER
{
    DWORD m_dwSignature;
    DWORD m_dwDataSize;
} FLASH_STREAM_HEADER, *PFLASH_STREAM_HEADER;

#pragma pack(pop)

static HRESULT LoadFlashMovieFromResource(ATL::CComPtr<IShockwaveFlash>& spShockwaveFlash,
    UINT nResourceID, LPCTSTR pszResourceType = RT_RCDATA)
{
    HMODULE hModule = ATL::_AtlBaseModule.GetModuleInstance();
    ATLASSUME(hModule != NULL);

    //HINSTANCE hResourceInstance = ATL::AtlFindResourceInstance(nResourceID, pszResourceType);
    //HRSRC hResource = ::FindResource(hResourceInstance, MAKEINTRESOURCE(nResourceID),
    //  pszResourceType);

    HRSRC hResource = ::FindResource(hModule, MAKEINTRESOURCE(nResourceID), pszResourceType);

    if (hResource == NULL)
        return HRESULT_FROM_WIN32(::GetLastError());

    DWORD dwResourceDataSize = ::SizeofResource(hModule, hResource);

    if (dwResourceDataSize == 0)
        return HRESULT_FROM_WIN32(::GetLastError());

    HGLOBAL hResourceLoaded = ::LoadResource(hModule, hResource);

    if (hResourceLoaded == NULL)
        return HRESULT_FROM_WIN32(::GetLastError());

    ATL::CComPtr<IStream> spStream;

    HRESULT hResult = ::CreateStreamOnHGlobal(NULL, TRUE, &spStream);

    if (FAILED(hResult))
        return hResult;

    FLASH_STREAM_HEADER fsh = {0x55665566, dwResourceDataSize};

    ULARGE_INTEGER uli = {sizeof (fsh) + dwResourceDataSize};

    hResult = spStream->SetSize(uli);

    if (FAILED(hResult))
        return hResult;

    hResult = spStream->Write(&fsh, sizeof (fsh), NULL);

    if (FAILED(hResult))
        return hResult;

    hResult = spStream->Write(reinterpret_cast<void*>(hResourceLoaded), dwResourceDataSize, NULL);

    if (FAILED(hResult))
        return hResult;

    uli.QuadPart = 0;

    hResult = spStream->Seek(*reinterpret_cast<PLARGE_INTEGER>(&uli), STREAM_SEEK_SET, NULL);

    if (FAILED(hResult))
        return hResult;

    ATL::CComPtr<IPersistStreamInit> spPersistStreamInit;

    hResult = spShockwaveFlash.QueryInterface(&spPersistStreamInit);

    if (SUCCEEDED(hResult))
        hResult = spPersistStreamInit->Load(spStream);

    return hResult;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top