Red de conocimiento informático - Material del sitio web - Cómo forzar a ffmpeg a generar fotogramas clave al codificar

Cómo forzar a ffmpeg a generar fotogramas clave al codificar

Cómo forzar a ffmpeg a generar fotogramas clave durante la codificación

AVCodecContext *c //Identificador del entorno del codificador

AVFrame* f //Fotograma de vídeo a codificar

/ *Esto se define en el archivo avcodec.h.

h se define así en el archivo

#define FF_I_TYPE 1 /// < Intra

#define FF_P_TYPE 2 /// < P TYPE 1 /// < Intra

#define FF_P_TYPE 2 /// < Predicho

#define FF_B_TYPE 3 /// < Bi-dir predicho

#define FF_S_TYPE 4 /// <Cambiar predicción

#define FF_BI_TYPE 7

*/

Configuración antes de codificar

f->pict_type=FF_I_TYPE

f- >key_frame=1;

Nota: Cuando este fotograma es un fotograma I, f->pict_type == FF_I_TYPE && f->key_frame==1

Luego codifica

*outsize = avcodec_encode_video(c,temp,outbuf_size,f);

Después de codificar, determine si es un fotograma clave mediante los siguientes parámetros:

key_frame =c->coded_frame- >key_frame

pict_type=c->coded_frame->pict_type;

key_frame==FF_I_TYPE && pict_type==1

¿Cómo extrae ffmpeg el fotograma clave del vídeo?

av_register_all();

if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL) !=0)

printf("error! \n");

if(av_find_stream_info(pFormatCtx)<0)

printf("error!\n");

videoStream=-1;

for(i=0; inb_streams; i++)

if(pFormatCtx->streams[i]->codec->codec_type ==CODEC_TYPE_VIDEO)

{

videoStream=i;

romper;

}

if(videoStream ==-1)

printf("¡error! \n");// No encontré una transmisión de video

// Obtener el puntero al contexto de codificación de la transmisión de video

pCodecCtx=pFormatCtx->streams[videoStream]-> codec;

Luego seleccione el códec a decodificar:

AVCodec *pCodec;

// Busque el códec para la transmisión de vídeo

pCodec=avcodec_find_decoder(pCodecCtx->codec_id);

if(pCodec==NULL)

printf("error!

\n");//Decodificador no encontrado

//Abrir decodificador

if(avcodec_open(pCodecCtx, pCodec)<0)

printf ("error !\n"); // No se puede abrir el decodificador

Ahora inicie el proceso de decodificación y extracción de fotogramas clave:

pFrame=avcodec _alloc_frame();

pFrameRGB = avcodec_alloc_frame();

numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->ancho, pCodecCtx->alto);

buffer=new uint8_t[numBytes];

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx-> ancho, pCodecCtx->alto);

pSWSCtx = sws_getContext(pCodecCtx->ancho, pCodecCtx->alto, pCodecCtx ->pix _fmt, pCodecCtx->ancho, pCodecCtx->alto, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

i=0;

while(av_read_frame (pFormatCtx ,&packet)>=0)

{

if(packet.stream_index==videoStream)

{

avcodec_decode_video( pCodecCtx, pFrame, &frameFinished,packet.data, paquete.size);

if (packet.size);

if(frameFinished)

{

p>

if(pFrame->key_frame==1) // este es el fotograma clave

{

sws_scale(pSWSCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx ->altura, pFrameRGB->datos, pFrameRGB->linesize

// Guardar en disco

char pic[200];

sprintf(pic , "pic%d.bmp",i);

i++;

av_create_bmp(pic,pFrameRGB->data[0], pCodecCtx->width,pCodecCtx- >altura, 24);

}

}

}

av_free_packet(&packet);

}

Finalmente, libere recursos y controladores<

// Libere imagen RGB

av_free(pFrameRGB

// Libere Marco YUV

av_free(pFrame);

>

sws_freeContext(pSWSCtx);

// Cerrar el decodificador (códec)

avcodec_close(pCodecCtx);

// Cerrar el archivo de vídeo

av_close_input_file(pFormatCtx)

ffmpeg SDK admite esta función y el siguiente código lo proporciona el equipo de ffmpeg.

int main()

{

SwsContext *pSWSCtx

AVFormatContext *pFormatCtx

const char; *filename="sample.mpg";

int i,videoStream, y_size

AVCodecContext *pCodecCtx

AVFrame *pFrame; p>AVFrame *pFrameRGB;

int numBytes, frameFinished;

int frameFinished;

uint8_t *buffer

paquete AVPacket;

av_register_all();

if(av_open_input_file(&.pFormatCtx, nombre de archivo, NULL, 0, NULL)!= 0)

printf("error! \n");

if(av_find_stream_info(pFormatCtx)<0)

printf("error!\n");

dump_format( pFormatCtx, 0 , nombre de archivo, false);

videoStream=-1;

for(i=0; inb_streams; i++)

if(pFormatCtx). ->.streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)

{

videoStream=i

break; p>}

if(pFormatCtx->.

if(videoStream==-1)

printf("error!\n");// Transmisión de vídeo no encontrada

pCodecCtx=pFormatCtx->streams[videoStream]->codec;

AVCodec * pCodec;

pCodec=avcodec_find_decoder(pCodecCtx->codec_id );

if(pCodec==NULL)

printf("error! \n");

if( avcodec_open(pCodecCtx, pCodec)<0)

printf("error!\n");

pFrame = avcodec_alloc_frame ();

pFrameRGB = avcodec_alloc_ frame();

numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx-> ancho,pCodecCtx->alto

búfer); =new uint8_t[numBytes];

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,pCodecCtx-> ancho, p

CodecCtx->alto);

pSWSCtx = sws_getContext(pCodecCtx->ancho, pCodecCtx->alto, pCodecCtx->pix_fmt, pCodecCtx-> ancho, pCodecCtx->alto, PIX _FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

i=0;

mientras(av_read_frame(pFormatCtx,&packet)>=0)

{

if( paquete.stream_index==videoStream)

{

avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, paquete.size);

avcodec_decode_video( pCodecCtx, pFrame, &frameFinished,packet.data, paquete.size)tamaño

if(frameFinished)

{

if(pFrame->key_frame= =1)//Los datos del fotograma clave se obtienen aquí

{

sws_scale(pSWSCtx, pFrame->data pFrame->linesize,0, pCodecCtx->height, pFrameRGB-> datos, pFrameRGB->tamaño de línea

i++

}

}

}

}

}

av _free_packet(&packet);

}

}

av_free(pFrameRGB); p>

} p>

av_free(pFrame);

sws_freeContext(pSWSCtx);

avcodec_ close(pCodecCtx);

av_close_input_file( pFormatCtx);

return 0;

}

live555+ffmpeg Cómo extraer fotogramas clave (fotograma I, fotograma P, fotograma B)

live555 +ffmpeg Cómo extraer fotogramas clave (I-frame, P-frame, B-frame) Al desarrollar reproductores multimedia de streaming, especialmente cuando se desarrolla en plataformas Windows Mobile y Symbian (S60), es probable que encuentra la necesidad de desarrollar su propia situación de jugador. La interfaz CVideoPlayUtility proporcionada por la plataforma S60 puede implementar un reproductor multimedia de transmisión, pero no se suscribe a la interfaz CVideoPlayUtility. La interfaz CVideoPlayUtility proporcionada por la plataforma S60 puede implementar un reproductor multimedia de transmisión, pero debido a que no es de código abierto, muchas operaciones están restringidas en comparación con el desarrollo de su propio reproductor. Live555 se utiliza principalmente para recibir transmisiones de red y ffmpeg se utiliza para codificar/decodificar los datos recibidos. El fotograma i, el fotograma p y el fotograma b son tres clasificaciones de transmisiones de vídeo. El fotograma i, también conocido como fotograma clave, es un fotograma básico. El fotograma p generalmente se determina en función del fotograma i. y el cuadro b requiere la información de los dos primeros cuadros.

Por ejemplo: la secuencia de entrada del codificador de vídeo 1 2 3 4 5 6 7I B B P B B I Tomamos 1, 2, 3... como el PTS de la secuencia de salida del codificador de vídeo simplificado: 1 4 2 3 7 5 6 Después de la decodificación, el secuencia Regresar a 1 2 3 7 5 6 Después de decodificar, la secuencia regresa a 1 2 3 7 5 6 Después de decodificar, la secuencia regresa a 1 2 3 7 5 6 Después de decodificar, la secuencia regresa al orden normal de 1 2 3 4 5 6 7. Por lo tanto, podemos juzgar el fotograma en función de avcodec_decode_video. Estrictamente hablando es 1 2 3 4. La secuencia es la siguiente: (1): Si decode_videoo_decode_video tiene éxito, es un fotograma I o un fotograma P (determina si es un fotograma I según AVFrame->keyframe). Si no es un cuadro I o P, solo puede ser un cuadro B (a juzgar por los puntos). (2): Utilice AVFrame->pict_type para sintetizar pts: if(FF_I_TYPE==imagen->pict_type) { Printlog("" } else if(FF_P_TYPE==imagen->pict_type) { Printlog("< PP>"); } else if(FF_B_TYPE==imagen-> pict_type) { Printlog(""); } else if(FF_S_TYPE==imagen->.pict_type) { Printlog(""); } else { Printlog(""); los fotogramas B normalmente no se imprimen porque los fotogramas I o P se decodifican correctamente.