Red de conocimiento informático - Material del sitio web - Cómo utilizar FFMPEG H264 para implementar la transmisión de datos RTP

Cómo utilizar FFMPEG H264 para implementar la transmisión de datos RTP

Entorno de desarrollo:

WINDOWS7 32bit

MINGW

eclipse juno cdt

1. Primero, compila FFMPEG,

a) Método 1: puede descargar el código fuente del sitio web oficial y compilarlo con MINGW (recuerde compilar para admitir H264. Por supuesto, debe descargar y compilar libx264 con anticipación. Si desea compilar, debe descargar y compile libx264 por adelantado. Hay algunas presentaciones en el foro de tecnología de videos)

b) Método 2: el método que ahorra más trabajo es descargar recursos que han sido compilados por otros, como ZeranoeFFmpeg. Descargue su versión de desarrollo, que contiene archivos de encabezado, bibliotecas y otras cosas necesarias. Por supuesto, esto ya es compatible con H264.

2. La siguiente es la parte del código:

a) Primero declare las variables necesarias:

AVFormatContext *fmtctx

AVStream; *video_st ;

AVCodec *video_codec;

const int FPS = 25 /* 25 imágenes/s */

const char *RDIP = "127.0. 0.1" ;

unsigned int RDPORT = 5678;

const unsigned int OUTWIDTH = 720;

const unsigned int OUTHEIGHT = 480;

av_register_all ();

avformat_network_init();

b) Inicializar contenedor AV

fmtctx = avformat_alloc_context(); Obtenga el formato de salida, aquí está el flujo de red RTP

fmtctx-gt; offormat = av_guess_format("rtp", NULL, NULL);

d) Abra el flujo de red

snprintf(fmtctx-gt; nombre de archivo, tamaño de(fmtctx-gt; nombre de archivo), "rtp://s:d", RDIP, RDPORT);

avio_open(amp; fmtctx-gt ; pb, fmtctx-gt; nombre de archivo, AVIO_FLAG_WRITE)

e) Comience a agregar transmisión de video H264

video_st = NULL;

La función add_video_stream está aquí:

add_video_stream(AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec _id)

{

AVCodecContext *c ;

AVStream *st;

/* Buscar codificador de vídeo*/

*codec = avcodec_find_encoder(codec_id); p>st = avformat_new_stream(oc, *codec);

c = st-gt;codec;

avcodec_get_context_defaults3(c, *codec);

c -gt; codec_ id = codec_id;

c-gt; ancho = OUTWIDTH;

c-gt; alto = OUTHEIGHT

c-gt; .den = FPS;

c-gt; tiempo_base.num = 1;

c-gt; pix_fmt = PIX_FMT_YUV420P; offormat-gt; bandera

s amp; AVFMT_GLOBALHEADER)

c-gt;flags|= CODEC_FLAG_GLOBAL_HEADER;

av_opt_set(c-gt;priv_data, "preset", "ultrafast", 0);

p>

av_opt_set(c-gt;priv_data, "tune", "stillimage, fastdecode, zerolatency", 0);

av_opt_set(c-gt;priv_data, "x264opts", "crf = 26: vbv-maxrate=728: vbv-bufsize=364: keyint=25", 0); return st; }

//Código abierto

avcodec_open2(video_st-gt ; codec, video_codec, NULL);

/* Escribe el encabezado de la transmisión (si lo hay). */ )

{

fill_yuv_image(m_pYUVFrame, video_st-gt; codec-gt; frame_number, OUTWIDTH, OUTHEIGHT);

/*imagen codificada*/

AVPacket pkt;

int got_output = 0;

av_init_packet(amp;pkt);

pkt.data = NULL; / Los datos del paquete serán asignados por el codificador

pkt.dts = AV_NOPTS_VALUE;

m_ pYUVFrame-gt; pts = video_st-gt; frame_number;

ret = avcodec_encode_video2(c,amp;pkt,frame,amp;got_output);

if (ret lt;0) {fprintf(stderr, "Error al codificar fotograma de vídeo: s\n", av_err2str (ret));

exit(1);

}

/* Si el tamaño es cero, la imagen se almacena en el buffer.

*/

if (got_output)

{

if (c-gt;coded_frame-gt;key_frame)pkt.flags |= AV_PKT_FLAG_KEY;

pkt.stream_index=st-gt;index;

if (pkt.pts ! = AV_NOPTS_VALUE )

{

pkt.pts = av_rescale_q (pkt.pts, video_st-gt; codec-gt; time_base, video_st-gt; time_base);

}

if (pkt.dts ! =AV_NOPTS_VALUE )

{

pkt.dts = av_rescale_q(pkt.dts, video_st-gt; codec-gt; time_base, video_st-gt; time_base;

}<); /p>

Escribe el archivo comprimido en el compilador. */

ret = av_interleaved_write_frame(oc, amp; pkt

}

else {

ret = 0;

p>

}

}

g) Función Fill_yuv_image:

//* Preparar una imagen virtual.

*/

static void fill_yuv_image(AVPicture *pict, int frame_ index, int width, int height)

{

int x, y, i;

i = frame_index;

/* Y */

para (y = 0; y lt; altura; y)

para (x = 0; x lt; ancho; x)

pict-gt; datos[0][y * pict-gt; tamaño de línea[0] x] = x y i * 3;

/* Cb y Cr */

para (y = 0; y lt; altura / 2; y)

{

para (x = 0; x lt; ancho / 2; * 2;

pict-gt;datos[2][y * pict-gt;tamaño de línea[2] x] = 64 x i * 5;

}

}

}

}

h) Imprimir información sdp, solo una vez La información sdp impresa se utiliza. en el reproductor VLC para finalizar la transmisión de vídeo en red

//Imprimir información sdp

char sdp[2048];

av_sdp_create(amp; fmtctx, 1, sdp , sizeof(sdp));

printf("s\n", sdp);

fflush(stdout);

i)Finalmente, haz algo trabajo de limpieza <

avcodec_free_frame(amp; m_pYUVFrame

av_write_trailer(fmtctx

/* Libera las transmisiones.*/

for (unsigned int i = 0; i lt; fmtctx-gt; nb_streams; i )

{

av_freep(amp; fmtctx-gt; streams-gt; codec);

av_freep(amp ; fmtctx-gt; transmisiones);

}

if(! (fmtctx-gt; offormat-gt; flagsamp; AVFMT_NOFILE))

/* Cierra el archivo de salida.

avio_close(fmtctx-gt;pb);

/*libera la transmisión*/

av_free(fmtctx);

3 , Compile el código, recuerde agregar el archivo de la biblioteca, ejecute el código una vez, no haga un bucle interminable, no configure ningún bucle, porque esto es para permitirle imprimir la información del archivo sdp.

Obtenga información de sdp, por ejemplo, la condensé de la siguiente manera:

c=IN IP4 127.0.0.1

m=video 56782 RTP/AVP 96

a =rtpmap: 96 H264/90000

a=framerate:25

a=fmtp:96 paquetes-mode=1

Guarde esta información en un archivo de texto y repita Nómbrelo con el sufijo sdp, como mySDP.sdp.

4. Descargue el reproductor VLC del sitio web oficial y vuelva a ejecutar el código anterior. Esta vez desea realizar el bucle. Lo que quieras hacer depende de ti. Esta vez es una prueba oficial. Después de ejecutar el código, use VLC para abrir el archivo sdp ahora y simplemente arrastre el archivo sdp directamente al reproductor VLC. Espere a que se almacene en búfer para ver los resultados.

5. Falta la parte de verificación de errores en el código, agréguela usted mismo.

6. En cuanto a la dirección IP, aquí está 127.0.0.1, que se utiliza para pruebas locales. Se puede cambiar a la dirección IP de la computadora de desarrollo que recibe los datos o a la dirección IP de la transmisión. DIRECCIÓN.