2010-03-29 15 views
8

Metaforma más eficiente para enviar imágenes a través de los procesos de

imágenes Pass generados por un solo proceso eficiente y a muy alta velocidad a otro proceso. Los dos procesos se ejecutan en la misma máquina y en el mismo escritorio. El sistema operativo puede ser WinXP, Vista y Win7.

Descripción detallada

El primer proceso es únicamente para el control de la comunicación con un dispositivo que produce las imágenes. Estas imágenes tienen un tamaño aproximado de 500x300 px y se pueden actualizar hasta varios cientos de veces por segundo. El segundo proceso necesita estas imágenes para procesarlas. El primer proceso utiliza una API de terceros para pintar las imágenes desde el dispositivo a un HDC. Este HDC debe ser provisto por mí.

Nota: Ya hay una conexión abierta entre los dos procesos. Se están comunicando a través de tuberías anónimas y comparten vistas de archivos mapeados en memoria.

Pensamientos

¿Cómo voy a lograr este objetivo con el menor trabajo posible? Y me refiero a que ambos trabajan para la computadora y para mí (por supuesto;)). Estoy usando Delphi, ¿entonces tal vez hay algún componente disponible para hacer esto? Creo que siempre podría pintar en el HDC de cualquier componente de imagen, guardar el contenido en la secuencia de la memoria, copiar el contenido a través del archivo mapeado en la memoria, descomprimirlo en el otro lado y pintarlo allí en el HDC de destino. También leí acerca de una interfaz de IPicture que se puede usar para ordenar imágenes. Lo necesito tan rápido como sea posible, así que cuanto menos sobrecarga, mejor. No quiero que la máquina se estrese solo copiando algunas imágenes.

¿Cuáles son sus ideas? Aprecio cada pensamiento sobre esto!

+1

si la imagen se actualiza varios cientos de veces por segundo, es posible que desee examinar cualquier técnica de procesamiento de video existente para manejar datos de video de gran ancho de banda en lugar de procesar imágenes. –

Respuesta

1

Ok, parece como si los archivos mapeados en memoria y las tuberías fueran el camino correcto. Eso no es tan malo porque los dos procesos ya comparten un archivo MMF y dos canalizaciones (para comunicación bidireccional). Lo único que queda por resolver es cómo pasar los datos con la menor cantidad de operaciones de copia posible.

El diseño que funciona bastante bien se ve de la siguiente manera (flujo secuencial):

Proceso 1 (quiere la imagen) Señal de

  • dar al proceso 2 (a través de la tubería 1) para almacenar la imagen en la memoria compartida
  • ir a dormir y esperar la respuesta (bloqueo de lectura de la tubería 2)

Proceso 2 (proporciona imágenes)

  • en la señal (a través de la tubería 1) despertar y decirle dispositivo de hardware para pintar a HDC 1 (esto está respaldado por la memoria compartida, véase más adelante)
  • dar señal a procesar 1 (a través de la tubería 2)
  • ir a dormir y esperar nuevo trabajo (a través de la tubería 1)

Proceso 1 (quiere la imagen)

  • en la señal (a través de la tubería 2) despertar y pintura de la memoria compartida de destino HDC 2

Ahora, para la transferencia de imágenes a través de memoria compartida (mi objetivo era utilizar no más de una operación adicional de copia):

Proceso 2 crea una HBITMAP través CreateDIBSection y proporciona el mango de la asignación del archivo y el offset de la vista mapeada. Por lo tanto, los datos de imagen viven en la memoria compartida. Esto crea un HBITMAP que se selecciona en HDC 1 (que también se crea mediante el proceso 2) y que se usará a partir de ahora mediante el proceso 2.

El proceso 1 usa StretchDIBits con un puntero a la memoria de la vista mapeada (como se describe here). Esta parece ser la única función para obtener bits de la memoria directamente en otro HDC (en este caso, HDC 2). Otras funciones las copiarían primero en algún buffer intermediario antes de poder transferirlas desde allí al HDC final.

Así que, al final, parece que los bits que se deben transferir son aproximadamente el doble que al principio. Pero creo que esto es tan bueno como lo es a menos que sea posible compartir los manejos de GDI entre los procesos.

Nota: Utilicé tuberías en lugar de señales porque también necesito transferir algunos datos adicionales.

11

Utilice Memory Mapped File.

Para obtener una referencia de Delphi, consulte Memory-mapped Files in Delphi y Shared Memory in Delphi.

Para un enfoque más versátil, puede considerar el uso de tuberías o el envío de datos de mapa de bits a través de TCP. Esto le permitiría distribuir los datos de imagen entre los nodos más fácilmente, si es necesario.

+0

Sí, podría hacerlo con un archivo mapeado en memoria. Todavía tendría que pintar la imagen en mi HDC, serializar la imagen en el archivo MMF, leerlos nuevamente en el otro lado y pintar la imagen en el HDC final. Parece que 4 operaciones de copia solían ser solo 1. Por lo tanto, estoy buscando una forma más eficiente. Pero si no hay ninguno, este es el camino a seguir, creo. –

4

Utilice la memoria compartida para pasar los datos de la imagen, y algo más (con nombre pipes, sockets, ...) para coordinar el traspaso.

3

En algunos casos, puede pasar identificadores HBITMAP a través de procesos. Lo he visto antes (sí, en XP/Vista), y me sorprendió como todos los demás en el equipo cuando uno de mis compañeros de trabajo me mostró.

Si la memoria me sirve correctamente, creo que funcionará si se asignó el HBITMAP con una de las funciones GDI (CreateBitmap, CreateCompatibleBitmap, CreateDIBitmap, etc.) Los identificadores HBIMAP creados por LoadBitmap no funcionarán, ya que es solo un puntero a un recurso en proceso.

Eso, y creo que cuando compartas el HBITMAP con el otro proceso, no intentes hacer nada especial con él aparte de las operaciones normales de BitBlt.

Al menos eso es lo que recuerdo. Tuvimos suerte porque nuestras bibliotecas gráficas ya estaban escritas para administrar todas las imágenes como HBITMAP.

YMMV

+0

+1 No lo usaría, pero sigue siendo interesante. –

+1

Esto es realmente interesante, aunque tampoco podría usarlo sin tener una mala sensación. Parece que pasar los manejos de GDI a través de los procesos es un poco como el juego: no debería funcionar, pero parece que sí a veces. (Ver http://stackoverflow.com/questions/2499487/sharing-hdc-between-different-processes donde primero pregunté acerca de este enfoque, ya que esperaba que fuera así de fácil.) –

+0

Pero ¿qué pasa con esto: http://stackoverflow.com/a/2500975/893350 Intenté esto y me aparece "Se produjo un error genérico en GDI +". Código Err: -2147467259 –

0

Como puedo ver esto, usted tiene dos opciones:

  1. Pass sólo la imagen mango/puntero a otro proceso, por lo que ambos procesos funcionan sólo en una colección de imágenes.
  2. Copie el contenido de la imagen a otro proceso y trabaje en una copia a partir de ese momento.

El mejor enfoque depende de su diseño. La mejor herramienta para ambos enfoques sería "archivos mapeados en memoria" o "conductos con nombre". Este es el más rápido que puedes obtener. Los archivos mapeados en memoria son, probablemente, la forma más rápida de comunicación entre procesos, pero tienen la ventaja de que no existe un paradigma de "cliente-servidor". Por lo tanto, debe sincronizar el acceso a MMF usted mismo. Las tuberías con nombre, por otro lado, son casi tan rápidas, pero tienen el paradigma de cliente-servidor integrado directamente en ellas. La diferencia de velocidad proviene principalmente de eso.

Ahora, debido a la velocidad de compartición de las actualizaciones, el primer enfoque podría ser mejor, pero luego hay que tener cuidado con la sincronización entre procesos para que no lean/escriban en una sola imagen al mismo tiempo. También podría usarse algún tipo de almacenamiento en caché u otras técnicas inteligentes, por lo que reducirá su tráfico al mínimo. Cuando se enfrenta un nivel tan alto de comunicaciones, siempre es aconsejable buscar los medios para reducir ese nivel si es posible.

Para una implementación muy rápida de IPC basada en tuberías con nombre, puede usar mi implementación IPC. Está orientado a mensajes para que no tenga que preocuparse por los detalles técnicos de la tubería. También utiliza el grupo de subprocesos detrás de escena y tiene una sobrecarga adicional mínima. Puede ponerlo a prueba y verlo usted mismo (un mensaje típico demora 0.1 ms para completar el ciclo solicitud-respuesta cliente-servidor).

+0

Gracias por vincularse a su implementación de IPC; puede ser necesario más adelante si tenemos que cruzar los límites de la computadora. Pero mi caso de uso es muy limitado en este momento. Una vez leí que diferentes dominios pueden causar problemas con tuberías con nombre, ¿lo has probado? –

+0

Probé en dos computadoras en la misma LAN, el mismo dominio. No probé otras combinaciones. Lo uso para la comunicación entre procesos en la misma computadora, ya que es más fácil de usar que MMF. No es necesario hacer ninguna sincronización. – Runner

Cuestiones relacionadas