Técnica de compresión de datos en tiempo real

Con cada vez más sistemas integrados conectados, el envío de información de estado de una máquina a otra se ha vuelto más común. Sin embargo, enviar grandes paquetes de datos a través de la red puede ser perjudicial tanto para el consumo de banda ancha como para un uso potente. Claro, si está hablando entre dos computadoras conectadas a una LAN gigabit y una instalación eléctrica montada en la pared, simplemente dispare ese paquete de 100 Kbytes a través de la red 10 veces por segundo. Pero si quiere ser más eficaz, puede que este truco le resulte útil.

Como experimento mental, asumiré un sistema que tiene una base de datos de información estatal que contiene 1,000 elementos. Parece un conjunto de REGISTROS:

typedef struct
{
  short topic;
  int data;
} RECORD;

No importa cuáles sean los temas y los datos. Realmente no importa si la información de su estado se ve así. Este es solo un ejemplo. Dado que se trata de información estatal, sin embargo, haremos una suposición importante. La mayoría de los datos no cambian con frecuencia. Lo que más a menudo significa, por supuesto, a menudo se podría discutir. Pero la idea es que si envío datos cada medio segundo o lo que sea, una gran cantidad no cambiará entre un envío y el siguiente.

Compresión

La respuesta más obvia es utilizar algún tipo de compresión. Si tiene tiempo para ejecutar un compresor con los datos y luego descomprimir todo dentro de su ventana, entonces esa es probablemente la respuesta, o al menos parte de ella. El problema, por supuesto, es que estos programas necesitan tiempo para funcionar. Otro problema es que, a veces, los datos no se comprimen bien y si agrega el nivel superior de compresión, es posible que no obtenga una reducción de datos o incluso puede hacer que envíe más datos.

Ofreceré un esquema de código continuo muy simple para nuestro sistema. Tratará la matriz de estado completa como una fila de bytes. Luego enviará un conjunto de paquetes que consisten en un cálculo y una carga útil. Si el recuento es positivo, entonces hay tantos bytes en la carga útil y simplemente se copian en la salida. Si el cálculo es negativo, entonces la magnitud es uno menos que un cálculo del byte de carga útil (es decir, -1 es un cálculo iterativo de 2). Limito arbitrariamente el tamaño de la iteración a 256. Un cálculo de 0 marca el final de la información de estado.

Si bien los planes de compresión funcionan, esto es bastante malo. Mi matriz de estado contiene 8,000 bytes (1,000 entradas). Si utilizo el algoritmo de compresión en una matriz de estado aleatorio, falla significativamente, es necesario enviar entre un 10 y un 12% más de bytes que simplemente enviar todo.

La reparación

Ahora te ríes y piensas en lo útil que es un algoritmo de compresión que falla en un 10% la mayor parte del tiempo. Pero, ¿y si pudieras hacer una cosa sencilla para solucionarlo? En particular, la razón por la que falla el algoritmo es que no se repiten suficientes datos para que esta compresión valga la pena. Incluso si utiliza un algoritmo de compresión "verdadero", casi siempre funcionarán mejor si los datos de compresión tienen secuencias más repetitivas. Aquí hay una razón por la que los formatos de archivo ya comprimidos no se comprimen bien: algunas secuencias iterativas ya se han eliminado.

Entonces, ¿cómo obtenemos datos más repetitivos? Después de todo, el estado es lo que es, ¿no es así? No puede organizar los datos de temperatura, humedad y posición para todas las secuencias de repetición de alineación, ¿verdad? Si piensa que la matriz está fija en el tiempo, probablemente sea cierto. Pero si empiezas a pensar en ello a tiempo, es posible que no.

¿Recuerdas cómo dije que supongo que la matriz de estado no cambia mucho entre las entregas? Aquí está la clave. Estos son los pasos:

  • Envíe la primera tabla de estado comprimida. Probablemente será más grande que el resto.
  • Antes de enviar la segunda matriz de estado, XOR con la anterior. Dado que no ha cambiado mucho, esto cambiará la mayor parte de la matriz de estado a ceros. Ceros repetidos.
  • Comprima y envíe la segunda tabla de estado.
  • Repita para la tercera, cuarta y todas las tablas siguientes.
  • MeSi está acostumbrado a usar programas como rsync, esta es la misma idea. No envíe todo, solo las piezas cambiadas. En el lado receptor, simplemente invierte la operación XOR usando la tabla de estado actual. Incluso si usa otro algoritmo de compresión, cambiar sus datos a ceros en su mayoría ayudará al compresor.

    Sin embargo, hay algunas advertencias. Primero, a menos que tu conexión sea perfecta, necesitas una forma de decirle al remitente que no has recibido la última actualización de estado, por lo que debería enviar una tabla completa nuevamente. También puede agregar algo de primera categoría cuando envía un fotograma completo (y tal vez lo envíe sin comprimir). También puede hacer que el remitente envíe periódicamente una tabla completa para ayudar a sincronizar.

    Simulado

    Para probar esta idea, escribí una simulación simple que puedes encontrar en GitHub. Debido a que el remitente y el receptor son realmente el mismo programa, no pretendí hacer un apretón de manos ack / nack o tomar las medidas necesarias para la resincronización. Querría agregar eso en la vida real.

    Escribí la simulación para usar un probador, que, en términos de originalidad, llamé prueba. Sin embargo, hay dos controladores de prueba, y puede seleccionar uno configurando TEST_MANUAL en 0 o 1. Si se establece en 0, el código usa dos datos de estado diferentes, que puede configurar en las funciones setstate0 y setstate1. Esto es bueno para probar un caso específico de depuración. Para simplificar las cosas, acabo de completar los primeros cuatro elementos, más el elemento 800 y el último elemento de la matriz de estado. Esto me permite continuar con un resultado de depuración mientras todavía puedo decir que las cosas están funcionando. Los primeros cuatro son simplemente prácticos. El de 800 muestra que los datos de aumento no están sincronizados y el último es adecuado para capturar casos de ángulos en los que se desborda el búfer.

    Sin embargo, también quería probar en una condición extensa, así que escribí al otro probador. Realiza cambios aleatorios en la tabla de estado en más de 100 repeticiones (no más de 20 cambios por repetición). Puede proporcionar una semilla en la línea de comando para obtener la misma ejecución de valores aleatorios para la prueba.

    Además de la semilla, puede prefijar la semilla con un signo (^) para suprimir el procesamiento XOR. Si no desea hacer el XOR, no tendrá muchas ejecuciones en los datos y su porcentaje será muy alto, tal vez más del 100%, lo que indica que envió más datos que solo enviar los bytes en el modo. Por ejemplo, aquí hay una ejecución que necesitaba enviar casi un 11% más de bytes de lo habitual sin usar el XOR.

alw@enterprise:~/tmp/state$ ./state ^143
TX/RX=8000000/8863392 (110.79)
Done

Con el XOR en su lugar, la misma corrida estaba al 2%, lo que significa que era un 98% más pequeña que los datos originales.

Puede leer el código para ver cómo se implementan las ideas anteriores. Hay algunas estructuras y funciones de datos clave que debe conocer:

  • Estado: el estado actual para transmitir
  • target: el estado actual del receptor
  • tx_prev: el estado anterior utilizado por el transmisor
  • rx_prev: el estado anterior utilizado por el receptor (ver más abajo)
  • recibir - El receptor simulado
  • xmit: el transmisor físico simulado (es decir, cualquier código que desee transmitir al receptor llama a esta función)
  • transmitir: envía el estado actual al receptor
  • Hablé sobre el uso del búfer rx_prev. Esto mantiene el estado anterior para que pueda XOR con los datos actuales después de la recepción. Sin embargo, puede sobrescribir los datos y guardar el búfer. El único problema es que no puedes usar llamadas efectivas como memcpy. De acuerdo, incluso después de memcpy tienes que ir a hacer el XOR si lo haces. Así que probablemente sea tan ancho como largo. Si tuviera que implementar esto en un sistema real, valdría la pena considerarlo.

    Ambos controladores de prueba usan memcmp para confirmar que el búfer del receptor es el mismo que el del transmisor. El probador aleatorio también calcula el porcentaje de datos enviados, que son los bytes recibidos divididos por el total de bytes enviados 100.

    Restricciones

    Como mencioné, no cuento con resincronizar en la simulación. Tampoco realizo comprobaciones de integridad como el pago o el CRC. Estos podrían estar relacionados en código real. Es fácil imaginar a un receptor calculando un CRC, comparándolo y enviando un acuse de recibo o un acuse de recibo negativo. También sería fácil imaginar que el transmisor envía algún tipo de cabezal y bandera síncronos para mostrar que el contenido es XOR o no. Incluso podría usar esa marca para indicar que los datos enviados no están comprimidos en absoluto, lo que le permitiría enviar el estado de referencia inicial sin compresión. Esto hará que el algoritmo sea aún más eficiente en la mayoría de los casos.

    Resultado

    La función de aleatorización cambia un número aleatorio de elementos en cada pasada, hasta 20 a la vez. Para 1000 registros, esto es un cambio del 2%. No es sorprendente que la cantidad de datos enviados en comparación con los datos recibidos sea de aproximadamente un 2%, como puede ver en el gráfico anterior. La correlación no es perfecta porque los datos son aleatorios, pero en general, el algoritmo funcionará bien hasta que gran parte de la matriz de estado cambie cada vez que la parte superior elimine alguna ventaja.

    Sin embargo, muchos proyectos no tendrán un estado que cambie con mucha frecuencia y esta es una excelente manera de publicar solo cambios. Esto funciona para cualquier estructura de datos. Sin embargo, tal como lo propuse, puede ver qué temas han cambiado y encontrar una manera de publicar solo los temas modificados. Sin embargo, tenga en cuenta que en mi ejemplo los temas son solo más datos y también cambian, por lo que sería más difícil en ese caso particular. Lo mío es que hay muchas formas de solucionar este problema.

    A veces parece que XOR no puede hacer nada. Hay muchos trucos de compresión, incluida la agitación, si sus datos pueden sobrevivir.

    • Ostraco dice:

      “La mayoría de los datos no cambian con frecuencia. "

      Lossless, contra perdido.

      • sasodomo dice:

        "La mayoría de los datos no cambian con frecuencia (en absoluto)". no tiene pérdidas, "La mayoría de los datos no cambian a menudo por un gran valor". es un perdedor.

      • Isaac dice:

        No. "Sin pérdidas" versus "sin pérdidas" es si la reconstrucción es * exactamente * igual a la fuente, o simplemente [somewhat/nearly/almost exactly] gusta.

    • kdev dice:

      Suena como un equivalente aproximado de i-frames y b-frames en video. En general, hace un buen trabajo, aunque tiene la desventaja de tener que sopesar el ancho de banda deseado con la duración máxima permitida de datos inexactos (es decir, qué tan lejos está dispuesto a llegar sin enviar un i-frame).

      • Al Williams dice:

        Esta es la parte que mencioné que no mostré. Si puede soltar un i-frame (para usar sus palabras), necesita una forma de recuperarlo. Sin embargo, la mayoría de estos sistemas reales tendrán ACK / NACK, por lo que siempre podrá saberlo después de que NACK envíe un i-frame.

      • Greenaum dice:

        Es mejor publicar diferencias, de verdad.

    • Yann Guidon / YGDES dice:

      Repite después de mi.
      La compresión es:
      * modelado, seguido de
      * codificación de entropía.
      Y su arte.

      • Al Williams dice:

        No, lo recuerdo. Realmente no publicito el esquema de compresión RLE. Lo mío con todo esto es que al hacer el XOR entre marcos de datos, y suponiendo que el marco completo no cambia cada vez, terminas con muchos ceros repetidos que se comprimen bien con algunas de algunas compresiones. esquemas.

        • torio dice:

          Encontré su método interesante y reemplazaría su compresión con la codificación de Huffman después del XOR.

          Teniendo solo números, y la mayoría de ellos siendo cero, Huffman trabajaría brevemente en ello.

          • Al Williams dice:

            Sí, hay infinitas formas de comprimirlo. La clave es que todas las partes que no han cambiado vayan a cero.

            • macegr dice:

              Un enfoque más o menos similar (en tamaño de paquete) sería simplemente tener un encabezado que contenga un registro de mapa de bits que indique qué información se está actualizando y seguirlo con solo esos bytes.

            • Al Williams dice:

              Hay muchas formas de hacerlo, incluido el etiquetado de cada elemento. Muchas, muchas opciones.

        • Gregkennedy dice:

          Similar a DPCM en lugar de PCM ... en lugar de mantener el nivel absoluto en cada intervalo de tiempo, mantenga el cambio del valor anterior. Ahora la onda sinusoidal cerca de los picos parece "... 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, -1, -1, -1, -1 ...". La codificación Huff funciona maravillosamente en esto.

    • Greg A. dice:

      Me enfrento a este problema exacto que codifica una serie de temperaturas a lo largo del tiempo, y el truco de XOR es bastante estúpido, creo que lo usaré gracias

      • Yann Guidon / YGDES dice:

        aquí está el flujo de datos continuo que puede ser procesado por el algoritmo de compresión 3R (reducción de intervalo reducido recursivamente), que he estado proyectando durante algún tiempo 🙂

    • dmcbeing dice:

      Mi uso favorito de la compresión fue este:

      Desarrollé para un dispositivo basado en 8051 que usaba una pantalla clásica de 128 × 64 paralela de 8 bits.
      La peor parte del desarrollo fue la carga, ya que se realizó a través de una conexión en serie de 9600 baudios.
      Cuando el programa binario alcanzó los 32k, el arranque comenzó a requerir un tiempo considerable y decidí que tenía suficiente e hice algo.
      Noté que la pantalla usaba solo los 6 bits menos significativos en un byte, desperdiciando 2 bits por imagen.
      Inmediatamente pensé en empaquetar esas piezas, e inmediatamente cambié de opinión sobre a quién le importa la compresión del 20% ... si comprimo, tengo que comprimir más del 50% (al menos en teoría).

      Lo que terminé con fue usar los 2 bits no utilizados como un contador RLE.
      Esto me permitió empaquetar hasta 4 bytes "sin procesar" en uno, permitiendo hasta un 75% de compresión, más parecidos.
      En la práctica, la mejor pantalla comprimida fue ~ 50% y la peor ~ 30%, por lo que ciertamente mejor que el enfoque de mapa de bits.

      Aunque al final no estoy seguro de si gané o perdí tiempo, ese truco de compresión me trajo más satisfacción que el resto del proyecto.

    • mi dice:

      uno podría enviar regularmente un hacha desde la matriz de estado, para ver si el receptor debe solicitar una actualización.

    • Al Williams dice:

      Ahora mi otro truco XOR favorito es https://patents.google.com/patent/US9438411B1

      La idea es simple: si el tamaño de su paquete es << 256, entonces hay algunos bytes que no usa en ningún paquete dado. Entonces identifica un byte distinto de cero que no aparece en la carga útil y XOR ese byte con todos los demás bytes. Luego usa 00 como byte inicial, seguido del byte de "clave" que usó, seguido del paquete XOR'd. Esto asegura que si ve 00, es el inicio del paquete sin la necesidad de un byte de escape (lo que hace que los paquetes tengan diferentes tamaños cada vez).

      Hay variaciones. Por ejemplo, si el paquete no tiene 00 y envía la inversa de la clave, puede omitir el XOR y enviar FF como clave invertida (esto significa que tampoco puede usar FF como clave).

      La mejora de Lojeck sobre el algoritmo es que si el tamaño de su paquete es mucho más pequeño, siempre puede seleccionar el byte clave de un conjunto y usar el conjunto que elija para identificar el tipo de paquete, ahorrando más espacio porque probablemente tuvo que enviarlo de todos modos. . En otras palabras, digamos que tiene paquetes de 10 bytes. Selecciona 11 teclas y llama a ese conjunto A. Luego, selecciona 11 teclas diferentes y llama a ese conjunto B. Digamos que el conjunto A es 10-1A y el conjunto B es 20-2A.

      Dado que solo hay 10 bytes, debe poder encontrar al menos una clave buena en cada conjunto. Entonces, si ve un paquete:

      00 15 …… ..
      Este es un paquete "A" con una clave de 15

      Pero si ves
      00 29 ......
      Este es el paquete "B" con clave 29

      Dependiendo del tamaño de los paquetes, puede tener varios tipos adicionales.

      Esto no es para la compresión, pero significa que puede obtener una sincronización perfecta si sabe que siempre está obteniendo un byte completo sin encabezado superior de "patrón de sincronización" o bytes de escape / rellenos de bytes. Sin embargo, es inútil si su canal de comunicación no puede entender dónde está el comienzo de un byte.

      • osannolik dice:

        Se parece a https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing

        • Al Williams dice:

          La misma razón para existir pero el algoritmo es diferente. En COBS, elimina cero bytes y los reemplaza con un número de byte, por lo que "sabe" que el byte es finalmente cero. Y el tamaño permanece constante porque eliminó el cero y agregó el número. Luego, obtiene su luz agregada a lo largo de un marcador de bytes al final y el puntero de inicio (2 bytes). El algoritmo anterior convierte el 0 en su lugar, pero requiere dos bytes de sobrecarga, lo mismo que COBS. Sin embargo, si puede reemplazar el marcador típico con la mejora de Lojeck, aún recuperará su byte adicional, algo que no podría hacer con COBS. Bueno ... tal vez podrías si cambiaras las partes superiores de la factura por el tamaño del paquete, que es algo así como lo que hace el Lojek. En otras palabras, el identificador de paquetes de Lojeck no funciona si su paquete es el máximo de todos modos, así que supongo que COBS podría intercambiar bits (es decir, el tamaño del paquete <127, luego 09 se desplaza al primer cero en un paquete, pero 89 es el mismo desplazamiento en el tipo de paquete " B "). COBS reclama un byte desde arriba, pero es porque no cuentan el separador de cuadros 0 como parte del protocolo. Por lo tanto, ambos agregan un byte más la separación de cuadros cero.

          Una de las desventajas menores de COBS es que, al menos conceptualmente, reemplaza cero al final de un subpaquete con un cálculo al comienzo del subpaquete, por lo que los datos en la implementación tienden a moverse sin un patrón específico. Con el método XOR, el byte 17 en el flujo de datos sin cifrar es el byte 19 en el flujo cifrado. Y dado que el desplazamiento está en la parte delantera, es muy fácil almacenar el byte 17 como el byte 17. Pero necesita un byte adicional de sobrecarga y también reduce el tamaño máximo de paquete en uno.

          Otra ventaja del algoritmo anterior es que puede usar una pequeña modificación para evitar realizar cualquier codificación o decodificación en paquetes que no contienen el separador de cuadros (que de hecho no debería ser nulo para ambos algoritmos, creo). Para mi algoritmo, lo hace aceptando que la clave se envíe al revés. Esto hace que 00 sea una clave legítima. Si el paquete no contiene 0, envía FF como clave, que es 0. Una implementación puede detectar esto y evitar aplicar XOR al búfer o una implementación ingenua puede XOR cada byte con 0, lo cual también está bien. COBS no es tan diferente, supongo. Si se da cuenta de que no necesita ceros, su byte de salto es 254 (o el tamaño de su paquete) y simplemente omite todo.

          Entonces, como algo más que una forma de despellejar al gato proverbial. COBS es unidireccional. El método clave es otro. Pero el resultado general es el mismo (0 separa bytes; 0 no aparece en ningún otro lugar; paquetes de tamaño fijo con dos bytes adicionales por paquete arriba). Pero los resultados detallados no lo son (procesamiento homogéneo de cada byte en su lugar más desplazamiento fijo versus procesamiento especial de algunos bytes con bytes deslizándose para descifrar / codificar).

          Por no decir que uno es mejor que el otro, simplemente diferente.

      • Brian Lojeck dice:

        Para ser justos, creo que también fui yo quien descubrió cómo tener indicadores de mensajes de inicio distintos de cero. ????
        (Considerando cuánto de esa patente fue el trabajo de A, tengo que quedarme con mis pocas contribuciones ... ????
        Sin embargo, puedo decir que en una FPGA, donde no siempre tenemos la flexibilidad de las asignaciones de memoria que hace uProc, esa patente hizo que "el programa en el que estábamos trabajando" realmente se uniera.

        • Al Williams dice:

          Ah, no lo recordaba, pero estoy seguro de que tienes razón. También es probablemente el implementador de algoritmos más experimentado del mundo 😉

          • Brian Lojeck dice:

            El segundo lugar es probablemente un pasante de verano en Moog.

            • Al Williams dice:

              Sabes que esta es la segunda vez que Buffalo aparece hoy.

    • danjovic dice:

      La compresión 64: 1 se puede lograr utilizando campos de bits en lugar de "dobles" para adquirir / procesar señales discretas en sistemas basados ​​en matlab / simulink, ¡y hay muchas bestias de este tipo alrededor!

    • dcfusor2015 dice:

      Buen trabajo, A.
      El intercambio a menudo vale la pena y, por supuesto, si el problema principal es la conexión BW y no el consumo de energía en el receptor, puede controlar razonablemente mucho ... la conexión no necesita ser bidireccional si "es suficiente "Se envían fotogramas clave para la aplicación.

    • Palmadita dice:

      Doo ... ¿por qué hacer xor en lugar de restar una buena idea?

      En principio quieres restar. Aquí está la cuestión: sus datos son en su mayoría estáticos, por lo que la distribución de valores es estricta en torno a un valor central, pero diferentes valores centrales. Si resta ese valor central (eso es lo que hace el ksor crudamente), comienza a normalizar las distribuciones. Pero la resta realmente * comienza * a normalizarlos (les da la misma media) mientras que xor toma la distribución, hace que el valor más probable * sea 0, pero los valores restantes están en todas partes.

      Como en, si sus valores fluctúan entre 0 y 1, el xor fluctuará entre 0 y 1. Si son 1023 y 1024, el xor fluctuará entre 0 y 2047. Si resta, ambos fluctuarán entre -1, 0 , y 1. Incluso en la codificación RLE burda, la resta aún debe tener una ligera ventaja.

      Si hace esto en FPGA, el xor puede tener sentido, pero en un microcontrolador / CPU, probablemente haya poca o ninguna ventaja entre xor y restar.

      • Al Williams dice:

        Creo que depende de la naturaleza de sus datos. Si tiene un montón de banderas o campos de bits, el XOR mostrará limpio lo que ha cambiado. La resta no servirá. Si tiene valores que fluctúan un poco, realmente está haciendo un delta y eso podría tener algún valor. Podría ser Es interesante cambiar la lógica en el código de prueba (debería ser simple) y ver si hay alguna ventaja.

        Lo malo es que te metes en firmeza y préstamos que creo que complican las cosas. XOR en anónimo está "en su lugar", no hay generación de préstamos / préstamos. Siendo realistas con este esquema, si no es cero, no importa que esté "cerca" a menos que muchas cosas tengan el mismo delta seguidas.

        • ccox dice:

          Realmente no se mete en una firma: se ejecuta con valores sin nombre y permite el excedente.
          Y la resta (predictor delta) tiene enormes ventajas si utiliza compresores Huffman o LZ. Consulte también TIFF, PNG, PSD, etc.

    • ESTOLA dice:

      La patente LZW ha expirado y se puede hacer cumplir fácilmente.

      LZW fue el algoritmo de compresión utilizado en GIF, lo que provocó una falla de patente que resultó en PNG.

      https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch

      • bufferscotch dice:

        Ah, entonces se pronuncia penj
        No pude resistir. Nunca me harán pronunciarlo tif jaja.

    • Enero 42 dice:

      Hay dos formas de comprimir estas cosas:
      1) dentro del único 'paquete'
      2) a tiempo

      Y te diriges a ambos. Sin embargo, supongo que para la mayoría de los problemas de programación integrada, la mejor ventaja sería con el tiempo: lo que haces con tu XOR.

      El problema es que si pasas mucho tiempo (según el comentario anterior con videos y fotogramas i y b) lo importante es qué tan confiable es la entrega, cómo sabes si tienes cada paquete, cómo aplicar para una nueva base. paquete si es necesario, o cómo (y si) tener un período de resincronización ...
      Hay muchos trabajos y cosas difíciles, y con el tiempo analiza los datos para ver cuál será la mejor estrategia de codificación (o de hecho, para adaptarla ..) 🙂

      • Al Williams dice:

        Entonces, los lugares que los he visto usar en el pasado han sido todos donde tienes una capa de transporte que maneja las cosas. Por ejemplo, si tengo dos computadoras en las que una intenta ser una copia de seguridad de la otra y tengo una conexión TCP con ellas, sé que estoy recibiendo los paquetes. Solo quiero minimizar la cantidad de datos a través de la conexión TCP (posiblemente lenta).

    • Isaac dice:

      Si está tratando con un video, simplemente elija MPEG. Muchos expertos * reales * han estado trabajando en él durante mucho tiempo, y realmente funciona. De hecho, utiliza, una tras otra, casi todas las técnicas de compresión mencionadas en estos comentarios. También un par más.

      • Al Williams dice:

        No, los comentarios anteriores sobre I-frames de la otra publicación fueron solo una analogía. Esto no se aplica a los videos.

        • Enero 42 dice:

    • CE dice:

      Ese pobre robot gato ... no ... quiere.

    • Dan Danknick dice:

      Eso es genial, Al. Siempre me gusta ser liviano y ágil frente a las típicas respuestas de “Ya sabes, esto se resolvió con filtros de Kalman”. Por cierto, eras uno de mis escritores favoritos en Nuts & Volts.

      "Dan".

    • Brent dice:

      Buen articulo. He intentado eludir los sistemas numéricos asimétricos y este código es un buen ejemplo de un código de estado finito de entropía.

    • Kazim Dusunmusoglu dice:

      Otro enfoque es enviar información de estado en momentos en que el estado es bastante diferente del valor recibido.
      en lugar de enviar actualizaciones a intervalos regulares. Estos enfoques se han explorado recientemente en el
      comunidad de la teoría de la información, es posible que desee consultar algunos artículos de investigación sobre la era de la información
      como:
      https://arxiv.org/abs/1701.06734
      http://www.ece.iisc.ernet.in/~htyagi/papers/PM-PP-HT-isit18.pdf
      http://ece.iisc.ernet.in/~parimal/papers/wcnc-2017-2.pdf
      https://infoscience.epfl.ch/record/224587/files/MG11_ARQ_Long.pdf
      https://ieeexplore.ieee.org/abstract/document/7786178/
      https://arxiv.org/abs/1806.06243

    • Guilherme dice:

      No entendí nada sobre esta publicación, pero vine aquí buscando una forma de comprimir datos en tiempo real desde un servidor ISCSI a una conexión de dispositivo invitado.
      ¿Alguna fuerza sobre él?

Alana Herrero
Alana Herrero

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *