---
title: Transmisión de memoria
slug: technical/es/transmision-de-memoria
docTags: 
createdAt: 2025-03-11T07:10:25.853Z
---

Como se describió anteriormente, el objeto *roMediaStreamer* proporciona un medio para especificar una única canalización flexible de procesamiento multimedia. Sin embargo, la canalización está limitada a tener una sola entrada y una sola salida. La función *transmisión de memoria* agrega un medio para bifurcar el flujo de datos de modo que se puedan crear múltiples salidas y realizar más de un hilo de procesamiento.

Tenga en cuenta que el memory streaming es especialmente importante al servir medios codificados en vivo, como HDM&#x49;**®** Input. El memory streaming garantiza que solo se necesite un único codificador para distribuir un flujo codificado en vivo a múltiples clientes.

# HTTP unicast múltiple

Para transmitir un flujo fuente mediante unicast a múltiples clientes, envíe la fuente (en este caso, HDMI Input codificada) a un flujo de memoria:

```text
m = CreateObject("roMediaStreamer")
m.SetPipeline("hdmi:, encoder:, mem:/livehdmi")
m.Start()
```

Ahora, una gran cantidad de clientes puede recibir el mismo flujo denominado "livehdmi" (el nombre es arbitrario, pero no debe entrar en conflicto con ningún otro flujo de memoria).

Cuando un cliente accede a la siguiente URL, el código del servidor multimedia HTTP crea una instancia independiente de *roMediaServer* que lee desde la fuente `mem:/livehdmi/stream.ts` y la reenvía al socket HTTP:

`http://IP_address:port/mem:/livehdmi/stream.ts`

Tenga en cuenta que `/stream.ts` debe agregarse al nombre del flujo de memoria para indicar que se debe utilizar el flujo completo.&#x20;

:::hint{type="info"}
En la instancia anterior, el código del media streamer creará realmente el componente fuente `memsimple:/livehdmi/stream.ts` porque utiliza menos recursos y es más eficiente.
:::

Una vez que se ha creado el flujo de memoria, también puede transmitirse simultáneamente mediante multicast utilizando otra instancia de Media Streamer:

```text
m1 = CreateObject("roMediaStreamer")
m1.SetPipeline("memsimple:/livehdmi/stream.ts,rtpsimple://239.192.0.0:5004/")
m1.Start()
```

# mem: y memsimple:

Al igual que con ciertos otros componentes, existe una versión "simple" y una "no simple" del memory streaming. La versión simple (`memsimple:`) solo puede utilizarse en una canalización con otros componentes simples, aunque los flujos de memoria simples pueden leer de flujos de memoria no simples `mem:` (como se muestra arriba, donde el componente `memsimple:/livehdmi` lee del componente `mem:/livehdmi`). Sin embargo, lo contrario no es posible: el componente fuente `mem:` no puede utilizarse para leer desde un flujo de memoria que se creó con el componente de destino `memsimple:` .

Debido a que los flujos de memoria simples no están indexados, no pueden admitir operaciones de transmisión HLS downstream (otros componentes no recibirán información sobre los segmentos HLS).

Como ocurre con otros componentes "simple", los flujos de memoria simples deben utilizarse siempre que sea posible porque consumen menos recursos.

# HLS unicast múltiple

El unicast múltiple HLS funciona de manera similar al ejemplo de multicast HTTP proporcionado anteriormente, pero con una excepción: los filtros de indexación de flujo solo funcionan en flujos leídos en el procesador de flujos de transporte, no en flujos leídos en el codificador (ambos manejados por el componente `mem:`). Como resultado, los flujos codificados como HDMI Input deben pasarse al componente `mem:` dos veces antes de que puedan transmitirse mediante multicast. Esto se logra fácilmente utilizando dos llamadas a `SetPipeline()` :

```text
m = CreateObject("roMediaStreamer")
m1 = CreateObject("roMediaStreamer")
m.SetPipeline("hdmi:,encoder:,mem:/hdmi_unindexed?size=5")
m1.SetPipeline("mem:/hdmi_unindexed/stream.ts ,mem:/hdmi_indexed?size=30&duration=5")
m.Start()
m1.Start()
```

Tenga en cuenta que debe especificarse un búfer de memoria más grande (30 MB en esta instancia) para el segundo componente `mem:` porque debe contener al menos cinco segmentos completos de 5 segundos en todo momento. Los clientes generalmente requieren 5 segmentos completos en todo momento para los flujos HLS, por lo que a menudo necesitarán esperar al menos 25 segundos antes de que el flujo pueda reproducirse correctamente.

Los clientes pueden acceder a los flujos HLS utilizando la siguiente URL:

`http://IP_address:port/mem:/hdmi_indexed/index.m3u8`

Al igual que el multicast HTTP, el media streamer generará instancias adicionales de *roMediaStreamer* para cada cliente que se conecte. Además de los clientes HLS, los clientes HTTP y RTSP también pueden conectarse al flujo indexado utilizando las siguientes URL:

## HTTP

`http://IP_address:port/mem:/hdmi_indexed/stream.ts`

## RTSP

`rtsp://IP_address:port/mem:/hdmi_indexed/stream.ts`

:::hint{type="info"}
El flujo indexado también puede transmitirse mediante multicast por otra instancia de *roMediaStreamer* .
:::

## Acceder a un flujo de memoria indexado

Como se muestra en ejemplos anteriores, agregar `stream.ts` al identificador del flujo de memoria denota el búfer completo, mientras que agregar `index.m3u8` a un flujo indexado (HLS) denota el archivo de índice completo. De forma similar, agregar el nombre de un segmento listado en el archivo de índice accederá a ese segmento durante el tiempo de vida de dicho segmento en el búfer del flujo de memoria. Por ejemplo, si el archivo de índice lista un segmento llamado `000179.ts` como disponible en el componente `mem:/componente de transmisión en vivo`, entonces el siguiente componente de origen puede utilizarse para recuperar ese segmento:

`mem:/livestream/000179.ts`

:::hint{type="info"}
El componente memsimple: también puede utilizarse para recuperar el segmento.
:::

# Ritmo del flujo de memoria

El flujo de datos hacia el flujo de memoria siempre se sincroniza en tiempo real para dar tiempo a los clientes de lectura a mantenerse al día. Una instancia de *roMediaStreamer* que está escribiendo nunca esperará a ninguno de los clientes de lectura; si algún cliente se queda demasiado atrás (lo cual se detecta cuando el extremo de escritura del FIFO sobrepasa el extremo de lectura del cliente), el cliente abortará y emitirá un mensaje EVENT\_EOS\_ERROR.

Debido a esta limitación, es importante tener en cuenta lo siguiente: si un flujo de memoria se utiliza para solucionar el hecho de que los datos no pueden pasarse directamente de un codificador a un decodificador (como en el siguiente ejemplo), entonces el procesamiento no puede realizarse más rápido que en tiempo real.

## Ejemplo

```text
m1 = CreateObject("roMediaStreamer")
m2 = CreateObject("roMediaStreamer")
m1.SetPipeline("hdmi:,encoder:,mem:/hdmi")
m2.SetPipeline("mem:/hdmi/stream.ts,decoder:,file:///file.ts")
m1.Start()
m2.Start()
```

# Estados del flujo de memoria

Un flujo de memoria solo se crea cuando el Media Streamer que lo nombra como destino está al menos en el estado CONNECTED. Esto significa que es posible conectar el pipeline (usando `Connect()`) que crea el flujo de memoria pero no iniciarlo. Se puede crear cualquier cantidad de Media Streamers que lean desde un flujo de memoria (e incluso iniciarlos) antes de que el Media Streamer original se inicie, comenzando el flujo de datos hacia el flujo de memoria.

Consulte [Máquina de estados de Media Streamer](docId\:B8aqcS-L-GwfRh9rttt7c) para obtener más información sobre los estados de *roMediaStreamer* .

# Cifrado y protección contra copia

En términos generales, una instancia de *roMediaStreamer* que lee desde un flujo de memoria adoptará el mismo cifrado/protección contra copia que la instancia asociada de *roMediaStreamer* que está escribiendo en él. Las reglas específicas son las siguientes:

- **Escritor simple**: Un destino `memsimple:` no puede marcarse como que requiere protección (ni puede recibir dicho flujo).
- **Lector simple**: Un origen `memsimple:` solo leerá desde un flujo de memoria que se marcó como no cifrado (sin requerir protección) cuando se creó.
- **Escritor no simple**: Un destino `mem:` se marcará como que requiere protección cuando se cree de acuerdo con el origen del pipeline. Si un flujo pasa a estar protegido más adelante, continuará funcionando si inicialmente se marcó como que requiere protección (opcionalmente con el parámetro `cifrar` ), de lo contrario se detendrá.
- **Lector no simple**: Un origen `mem:` hereda el estado de protección de su escritor asociado y, por lo tanto, su salida finalmente requerirá protección HDCP o DTCP si el origen se marcó de manera similar.

