Protocolo RTSP, pero qué es RTSP?
El protocolo RTSP es un protocolo basado en texto, nos permite realizar peticiones desde un cliente hacia un servidor remoto, lo qué facilita mucho la implementacion de este protocolo en un lenguaje de alto nivel,y cabe destacar qué tiene un gran parecido al protocolo tambien basado en TEXTO qué es el famoso protocolo HTTP.
Es viable hacer streaming bajo MOTION JPEG?
Bajo mi propia experiencia, el protocolo HTTP bajo motion jpeg no es viable para:
Sistemas de videovigilancia qué exigan videos en alta definicion
Usuarios qué necesiten realizar streaming on demand, debido a qué es necesario realizar transcoding para qué un reproductor externo reproduzca la grabacion, el video no veria exactamente impecable ( bloqueos en la imagen al realizar el visionado en el player flash )
En el caso de grabar desde una camara IP, no es nada recomendable utilizar motion jpeg, las camaras actuales utilizan H264 y rtsp totalmente recomendable para streaming ).
Qué es LIVE555?
Live555 es un entorno de desarollo multiplataforma utilizado por vlc, mplayer y otros sistemas de reproduccion multimedia, qué nos permitiran acceder a una fuente rtsp, y codificarla en caso necesario en otro formato, ya qué las fuentes rtsp originalmente qué se emiten en h264 el fichero dumpeado no suele poder reproducirse bajo ningun concepto en ningun player, y se tiene qué recodificar en flv o en otro formato reproducible bajo el entorno donde trabajemos.
Lo qué sucede es qué ffmpeg sí probamos a codificar el fichero h264 sin insertar el start_code, y otros datos codificados en base64 no sera capaz de reconocerlo como un fichero encapsulado en h264 por eso se requiere insertar estas cabezeras en el flujo qué nos llege de live555 ( aunqué no es tan facil como parece ), debido a qué estos datos se deben concatenar con el buffer qué llega de la fuente original rtsp.
Una vez tenemos un buffer qué es reconocido como un buffer encapsulado en h264, podemos pasarselo a un decodificador qué se encarga de insertar los datos decodificados en un frame distinto, para qué despues libavcodec u otro codificador qué useis, sea capaz de recodificar los datos recodigos por el decodificador, y lo recodifique en otro formato, especificando un timestamp correcto, y otros valores como la cantidad de cuadros por segundo, el bitrate el sample rate, etc.
Código:
uint8_t * buffer = new uint8_t[1024];
int ptrFinished = 0;
AVFrame * pFrame = avcodec_alloc_frame();
avcodec_decode_video2(avcodecCtx,pFrame,&ptrFinished,&pkt);
AVFrame = recoge los datos decodificados
ptrFinished = evalua si ha terminado de decodificar los datos, o no.
Cada vez qué se termine de abrir un codec, realizar el proceso de decodificacion/codificacion, los punteros se deben liberar, y la conexion se debe de cerrar para no malgastar memoria incesaria.
libavcodec proporciona lo siguiente:
Código:
av_freep(pkt);
pkt = AVPacket es una estructura qué contiene los siguientes miembros:
data = datos decodificados.
size = buffer size.
pkt es un puntero instanciado de esta estructura, qué se sobrecarga en avcodec_decode_vide o para decodificar los datos de video
Abriendo una conexion con LIVE555 y el servidor RTSP
Código:
this->client = RTSPClient::createNew(*this->env, 1,"User agent");
Abre una conexion con el servidor, *this->env, es un puntero qué se instancia de la siguiente manera:
Código:
TaskScheduler * scheduler = BasicTaskScheduler::createNew();
this->env = BasicUsageEnvironment::createNew(*scheduler);
Es necesario cada vez qué creemos instancias de un nuevo RTSPClient, para conectarnos.
el segundo parametro especifia el nivel de debug qué se utilizara ( modo verbose ) para imprimir cada suceso qué vaya pasando en el proceso de conexion con el servidor.
"User Agent" es el user agent del servidor, es un nombre de descripcion qué se utiliza para describir el cliente qué se ha utilizado en la conexion final con el servidor.
Ficheros de cabezera:
Código:
#include
#include
#include "GroupsockHelper.hh"
Procesando la conexion con el servidor
Código:
char * describe_options = this->client->describeURL(this->rtsp_url);
Enviamos el comando DESCRIBE al servidor remoto ,para listar los posibles comandos qué estan disponibles en el servidor.
Código:
sdp_description = strDup(describe_options);
Copiamos describe_options a una variable publica para poder acceder desde otros metodos o funciones publicas.
Código:
UsageEnvironment * environment = this->env;
char * sdp = this->getSDP();
if ( environment != NULL )
{
this->session = MediaSession::createNew(*environment,sdp);
}
sdp = obtenemos la descripcion SDP.
enviromment = obtenemos el puntero instanciado de BasicUsageEnvironme nt, qué sera construido una vez llamado al metodo o funcion validos qué se encarguen de retornar un puntero non null.
Creamos una sesion rtsp asignando a el puntero publico, los datos qué nos llegen de la llamada MediaSession::createNew(*environment,sdp);
esta session nos permitira identificar los codecs de audio y video qué utilizan los flujos y subflujos de audio utilizados por lo qué nos esta enviando.
Código:
this->it = new MediaSubsessionIterator(*this->session);
this->it hace referencia a MediaSubSessionIter ator y es sobrecargado con un puntero del tipo MediaSubsession ,para recoger el numero de flujos del qué dispone.
Los flujos se inicializan de la siguiente manera:
Código:
if ( this->subsession->initiate() )
true si se han iniciado, false si no se han iniciado alguno de los flujos.
Ahora fuera del bucle, volvemos a recorrer los flujos volviendo a crear otro iterador, o directamente sobreescribiendo el qué tenemos así:
Código:
this->it = new MediaSubSessionIterator(*this->session);
Una vez tenemos sobreescrito el puntero, volvemos a recorrer los flujos disponibles:
Código:
while ( ( subsessionSecond = it->next() )!= NULL )
Código:
cliente->setupMediaSubsession(*this->session)
Enviamos el comando SETUP, para qué directamente nos responda con el flujo de datos qué nos envia el servidor, antes de eso lo deberemos identificar como un flujo h264 o un flujo de audio ( otro ).
Código:
if ( strcmp(session->codecName(),"H264") == 0 ) LO QUÉ SEA...
dentro de lo qué sea podriamos escribir lo siguiente:
Código:
H264VideoFileSink * fileSink = H264VideoFileSink::createNew(*this->env, out_filename,
this->subsession->fmtp_spropparametersets(),
100000, false);
*this->env, parametro obligatorio
out_filename = fichero de salida.
fmtp_spropparameter sets = cabezeras codificadas en base64.
1000000 = bufferSize.
false = podria ser true, si queremos qué cree mas ficheros, false si solo es uno.
Compilacion para Linux de live555
Código:
./genMakeFiles linux
make install
Compilacion para windows
Código:
./genMakeFiles mingw
make install
Compilacion para mac os x
Código:
./genMakeFiles macosx
make install
Y hasta aquí el tutorial
Saludos.
No hay comentarios:
Publicar un comentario