Pergunta

Eu decodificação de vídeo através de libavcodec, usando o seguinte 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);
}

O código funciona corretamente, mas é necessário converter cada quadro para o formato necessário.É possível definir o formato de pixel para a decodificação para obter o formato correto, sem sws_scale?

Muito obrigado por suas respostas.

Foi útil?

Solução

ffmpeg's AVCodec instâncias (estático decodificador de "fábrica" de objetos) cada definir uma matriz de formatos de pixel que eles suportam, finalizado pelo valor -1.

O AVCodecContext (decodificador de instância) objetos têm uma função de retorno de chamada ponteiro chamado get_format:é um ponteiro de função em que se estrutura.

Esta função de retorno de chamada é chamada, em algum momento da inicialização do codec, com o AVCodec fábrica do objeto de matriz de formatos suportados, e o retorno de chamada é suposto escolher um dos formatos a partir dessa matriz (uma espécie de "escolha uma carta, qualquer carta") e retornar o valor.A implementação padrão desse get_format de retorno de chamada é uma função chamada avcodec_default_get_format.(Esta é instalado avcodec_get_context_defaults2).Esta função padrão implementa a "escolha um formato de" lógica bastante simples:ele escolhe o primeiro elemento da matriz, o que não é um hardware de aceleração-somente o formato de pixel.

Se você deseja que o codec para trabalhar com um diferente formato de pixel, o que você pode fazer é instalar o seu próprio get_format chamada de retorno para o objeto de contexto.No entanto, o retorno de chamada deve retornar a um dos valores em matriz (como a escolha de um menu).Ele não pode retornar um valor arbitrário.O codec irá apenas suporte a formatos que especifica na matriz.

Andar a variedade de formatos disponíveis e escolha a melhor.Se você tiver sorte, ele é exatamente o que você realmente quer e o sws_scale função não tem a fazer pixel de conversão de formato.(Se, além disso, você não solicitação de escala ou cortar a imagem, sws_scale deve reconhecer que a conversão é um noop.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top