c++ - MJPEG streaming y decodificación
opencv rtsp (1)
¿Es esta una cámara IP de Axis? De cualquier manera, la mayoría de las cámaras IP que proporcionan el flujo de MPEG4 RTSP se pueden decodificar usando OpenCV usando cvCreateFileCapture_FFMPEG . Sin embargo, el códec MJPEG del decodificador ffmpeg tiene problemas no resueltos ampliamente conocidos. Estoy seguro de que habrías recibido un error similar a
[ingenient @ 0x97d20c0]Could not find codec parameters (Video: mjpeg)
Opción 1: Uso de opencv, libcurl y libjpeg
Para ver la transmisión mjpeg en opencv, eche un vistazo a la siguiente implementación
http://www.eecs.ucf.edu/~rpatrick/code/onelinksys.c o http://cse.unl.edu/~rpatrick/code/onelinksys.c
Opción 2: usar gstreamer (no opencv)
Recomendaría mirar gstreamer si su objetivo es simplemente ver o guardar imágenes jpeg
Para ver la secuencia MJPEG, se puede ejecutar la cadena de canal de medios de la siguiente manera
gst-launch -v souphttpsrc location="http://[ip]:[port]/[dir]/xxx.cgi" do-timestamp=true is_live=true ! multipartdemux ! jpegdec ! ffmpegcolorspace ! autovideosink
Para RTSP
gst-launch -v rtspsrc location="rtsp://[user]:[pass]@[ip]:[port]/[dir]/xxx.amp" debug=1 ! rtpmp4vdepay ! mpeg4videoparse ! ffdec_mpeg4 ! ffmpegcolorspace! autovideosink
Para trabajar con C API ver
Para un ejemplo simple, eche un vistazo a mi otra publicación en rtsp para construir el canal de medios de la API de gstreamer C (Esto es igual que la cadena de inicio de gst, pero más bien implementado como una API de C)
Jugando RTSP con python-gstreamer
Para guardar el flujo de MJPEG como múltiples imágenes de la tubería (Pongamos un BIN de giro vertical y conectemos los PADS al BINS anterior y al siguiente para hacerlo más elegante)
gst-launch souphttpsrc location="http://[ip]:[port]/[dir]/xxx.cgi" do-timestamp=true is_live=true ! multipartdemux ! jpegdec ! videoflip method=vertical-flip ! jpegenc ! multifilesink location=image-out-%05d.jpg
Quizás también merezca la pena echar un vistazo a gst-opencv.
ACTUALIZAR:
Opción 3: usar gstreamer, Named Pipe y opencv
En Linux, uno puede obtener mjpeg stream y convertirlo a mpeg4 y alimentarlo a una tubería con nombre. Luego lea los datos de la tubería nombrada en opencv
Paso 1. Crear una tubería con nombre
mkfifo stream_fifo
Paso 2. Crear opencvvideo_test.c
// compile with gcc -ggdb `pkg-config --cflags --libs opencv` opencvvideo_test.c -o opencvvideo_test
#include <stdio.h>
#include "highgui.h"
#include "cv.h"
int main( int argc, char** argv){
IplImage *frame;
int key;
/* supply the AVI file to play */
assert( argc == 2 );
/* load the AVI file */
CvCapture *capture = cvCreateFileCapture(argv[1]) ;//cvCaptureFromAVI( argv[1] );
/* always check */
if( !capture ) return 1;
/* get fps, needed to set the delay */
int fps = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );
int frameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int frameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
/* display video */
cvNamedWindow( "video", CV_WINDOW_AUTOSIZE );
while( key != ''q'' ) {
double t1=(double)cvGetTickCount();
/* get a frame */
frame = cvQueryFrame( capture );
double t2=(double)cvGetTickCount();
printf("time: %gms fps: %.2g/n",(t2-t1)/(cvGetTickFrequency()*1000.), 1000./((t2-t1)/(cvGetTickFrequency()*1000.)));
/* always check */
if( !frame ) break;
/* display frame */
cvShowImage( "video", frame );
/* quit if user press ''q'' */
key = cvWaitKey( 1000 / fps );
}
/* free memory */
cvReleaseCapture( &capture );
cvDestroyWindow( "video" );
return 0;
}
Paso 3. Prepárese para convertir de MJPEG a MPEG4 usando gstreamer (tasa crítica de tramas entrantes)
gst-launch -v souphttpsrc location="http://<ip>/cgi_bin/<mjpeg>.cgi" do-timestamp=true is_live=true ! multipartdemux ! jpegdec ! queue ! videoscale ! ''video/x-raw-yuv, width=640, height=480''! queue ! videorate ! ''video/x-raw-yuv,framerate=30/1'' ! queue ! ffmpegcolorspace ! ''video/x-raw-yuv,format=(fourcc)I420'' ! ffenc_mpeg4 ! queue ! filesink location=stream_fifo
Paso 4. Display Stream en OpenCV
./opencvvideo_test stream_fifo
Quiero recibir imágenes JPEG de una cámara IP (sobre RTSP). Para esto, probé cvCreateFileCapture_FFMPEG
en OpenCV. Pero ffmpeg parece tener algún problema con el formato MJPEG de la transmisión (ya que trata de detectar automáticamente la información de transmisión) y termino con el siguiente error
mjpeg: unsupported coding type
Yo, entonces, decidí usar live555 para la transmisión. Hasta ahora, puedo establecer con éxito la transmisión y captura de imágenes (no decodificadas) a través de openRTSP.
La pregunta es cómo puedo hacer esto en mi aplicación, por ejemplo, en OpenCV. ¿Cómo puedo usar openRTSP en OpenCV para obtener imágenes y guardarlas en formato JPEG?
He escuchado que los datos de openRTSP se pueden enviar a un búfer (o una tubería con nombre) y luego leerlos en IplImage
de OpenCV. Pero no sé cómo hacer esto.
Realmente apreciaré cualquier ayuda / sugerencia sobre este problema. Necesito respuestas de cualquiera de las siguientes preguntas:
- ¿Cómo puedo deshabilitar la detección automática de información de flujo de ffmpeg y especificar mi propio formato (mjpeg), o
- ¿Cómo puedo usar openRTSP en OpenCV?
Saludos,