Pregunta

Decodifico video a través de libavcodec, usando el siguiente código:

//Open input file
if(avformat_open_input(&ctx, filename, NULL, NULL)!=0)
    return FALSE; // Couldn't open file
if(avformat_find_stream_info(ctx, NULL)<0)
    return FALSE; // Couldn't find stream information
videoStream = -1;
//find video stream
for(i=0; i<ctx->nb_streams; i++)
{       
    if((ctx->streams[i])->codec->codec_type==AVMEDIA_TYPE_VIDEO)
    {
        videoStream=i;
        break;
    }
}
if (videoStream == -1)
    return FALSE; // Didn't find a video stream
video_codec_ctx=ctx->streams[videoStream]->codec;
//find decoder
video_codec=avcodec_find_decoder(video_codec_ctx->codec_id);
if(video_codec==NULL)
    return FALSE; // Codec not found
if(avcodec_open(video_codec_ctx, video_codec)<0)
    return -1; // Could not open codec
video_frame=avcodec_alloc_frame();
scaled_frame=avcodec_alloc_frame();
static struct SwsContext *img_convert_ctx; 
if(img_convert_ctx == NULL) 
{
      int w = video_codec_ctx->width;
      int h = video_codec_ctx->height;
      img_convert_ctx = sws_getContext(w, h, 
                        video_codec_ctx->pix_fmt, 
                        w, h, dst_pix_fmt, SWS_BICUBIC, 
                        NULL, NULL, NULL);
      if(img_convert_ctx == NULL) {
        fprintf(stderr, "Cannot initialize the conversion context!\n");
        return FALSE;
      }
}
while(b_play) 
{
    if (av_read_frame(ctx, &packet) < 0)
    {
        break;
    }
    if(packet.stream_index==videoStream) {
    // Decode video frame   
        avcodec_decode_video2(video_codec_ctx, video_frame, &frameFinished,
                         &packet);
        // Did we get a video frame?
        if(frameFinished) 
        {
            if (video_codec_ctx->pix_fmt != dst_pix_fmt)
            {                       
                if (video_codec_ctx->pix_fmt != dst_pix_fmt)            
                     sws_scale(img_convert_ctx, video_frame->data, 
                              video_frame->linesize, 0, 
                              video_codec_ctx->height, 
                              scaled_frame->data, scaled_frame->linesize);              
            }           
        }
}
av_free_packet(&packet);
}

El código funciona correctamente, pero es necesario convertir cada fotograma al formato requerido.¿Es posible configurar el formato de píxeles para decodificar para obtener el formato correcto sin sws_scale?

Muchas gracias por tus respuestas.

¿Fue útil?

Solución

ffmpeg's AVCodec Las instancias (objetos "de fábrica" ​​del decodificador estático) definen cada una una matriz de formatos de píxeles que admiten, terminada en el valor -1.

El AVCodecContext (instancia de decodificador) los objetos tienen un puntero de función de devolución de llamada llamado get_format:es un puntero de función en esa estructura.

Esta función de devolución de llamada se llama, en algún momento de la inicialización del códec, con el AVCodec matriz de formatos admitidos del objeto de fábrica, y se supone que la devolución de llamada elige uno de los formatos de esa matriz (algo así como "elige una tarjeta, cualquier tarjeta") y devuelve ese valor.La implementación predeterminada de este get_format la devolución de llamada es una función llamada avcodec_default_get_format.(Esto está instalado avcodec_get_context_defaults2).Esta función predeterminada implementa la lógica de "elegir un formato" de manera bastante simple:elige el primer elemento de la matriz que no es un formato de píxel de aceleración de hardware únicamente.

Si quieres que el códec funcione con un formato de píxeles diferente, lo que puedes hacer es instalar el tuyo propio get_format devolución de llamada en el objeto de contexto.Sin embargo, la devolución de llamada debe devolver uno de los valores de la matriz (como elegir de un menú).No puede devolver un valor arbitrario.El códec solo admitirá los formatos que especifica en la matriz.

Explore la variedad de formatos disponibles y elija el mejor.Si tienes suerte, será exactamente el que realmente quieres y el sws_scale La función no tendrá que realizar la conversión de formato de píxeles.(Si, además, no solicita escalar o recortar la imagen, sws_scale debería reconocer que la conversión es un error).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top