Cómo forzar a ffmpeg a generar fotogramas clave al codificar
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; 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; 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("