2014-06-20 4 views
2

내 질문이 너무 잘 형식화되지 않은 경우 미안 해요, 지금은 FFmpeg 및 Libav 시작했다. 나는 미디어 형식에 관해서 너무 지식이 없다. 나는 지난 달이 주제에 대해 내가 아는 모든 것을 거의 배웠다. 내가 할 수있는 한 많은 연구를 해왔고 꽤 멀리까지 갔지만, 이제는 내 질문이 실제로 무엇인지 거의 확신 할 수없는 시점에 이르렀다. 이것들은 관측과 비슷하지만, 전문가 중 일부가 나를 도와 줄 수 있기를 바랍니다.Libav H264로 트랜스 코딩 : 프레임이 누락되었습니다

FFmpeg의 라이브러리를 사용하여 Gif를 MP4로 코드 변환하려고하지만 H264 코덱을 사용할 때 이상한 문제가 발생합니다. 트랜스 코딩 루프에서, 나는 (av_write_frame의 반환 값을 검증함으로써) 내가 쓴 프레임의 수를 유지한다. 특정 샘플에서는 총 166 개의 프레임을 셉니다. FFmpeg (변환 된 프로그램, Gif에서 MP4 로의 변환을 사용하여 에뮬레이트하고 싶은 기능)를 사용하여 FFmpeg의 변환 된 파일을 검사하면 FFmpeg의 출력 파일에도 166 프레임이있는 것으로 보이지만 FFprobe로 출력을 검사 할 때 144 프레임 만 가질 수 있습니다. 재미있는 점은 H264에서 MPEG4로 코덱을 변경하면 FFmpeg의 출력과 카운터가 일치하는 166 개의 프레임이 출력되는 것입니다. 필자는 다른 Gif 파일을 사용하여 비슷한 결과를 얻었는데, 필자의 프레임 카운터는 FFmpeg의 출력 프레임 수와 일치하지만 출력은 일부 프레임을 떨어 뜨리는 것으로 보입니다.

인코더 설정 :

ostream_codec_context->codec_id = CODEC_IN_USE; //CODEC_ID_H264 or CODEC_ID_MPEG4 
ostream_codec_context->pix_fmt = AV_PIX_FMT_YUV420P; 
ostream_codec_context->codec_type = AVMEDIA_TYPE_VIDEO; 
ostream_codec_context->flags = CODEC_FLAG_GLOBAL_HEADER; 
ostream_codec_context->profile = FF_PROFILE_MPEG4_SIMPLE; 

ostream_codec_context->gop_size = istream_codec_context->gop_size; 
ostream_codec_context->time_base = istream_codec_context->time_base; 

ostream_codec_context->width = (istream_codec_context->width/2) * 2; 
ostream_codec_context->height = (istream_codec_context->height/2) * 2;  

트랜스 코딩 루프 : 나는 또한에 문제가있어 일부 오류 검사 코드 및 디버깅 문

avformat_write_header(oformat_context, NULL); 
while (av_read_frame(iformat_context, &packet) == 0) 
{ 
    if (packet.stream_index == istream_index) 
    { 
     avcodec_decode_video2(istream_codec_context, ipicture, &full_frame, &packet); 
     if (full_frame) 
     { 
     sws_scale(image_conversion_context, 
        (uint8_t const * const *) ipicture->data, 
        ipicture->linesize, 0, istream_codec_context->height, 
        opicture->data, opicture->linesize); 

     opicture->pts = av_rescale_q(packet.pts, istream_codec_context->time_base, 
             ostream->time_base); 

     ret = avcodec_encode_video2(ostream_codec_context, &packet, 
            opicture, &got_packet); 
     if (!ret) 
     { 
      ret = av_write_frame(oformat_context, &packet); 
      if (ret < 0) 
       num_frames_written++; 
     } 
     } 
    } 
    av_free_packet(&packet); 
    av_init_packet(&packet); 
} 

을 생략 한

내 출력의 비트율. 나머지 인코더 설정으로 설정을 시도 할 수 있지만 FFprobe가 나타내는 비트 전송률은 이 아니며 코덱 컨텍스트와 동일합니다. 비트 레이트를 상수 값으로 설정하여 출력에 어떤 영향을 주는지 보았습니다. 출력의 비트 전송률이 내가 제공 한 것과 같지 않지만 입력이 확실히 출력의 실제 비트에 영향을 미치는 것으로 나타났습니다. -율. 내 문제를 다루는 것으로 보이는 게시물을 발견했지만 거기에 나와있는 해결책이 내 문제를 해결하지 못하는 것 같습니다.

http://ffmpeg.org/pipermail/libav-user/2012-July/002492.html

언급 할 가치가 또 다른 것은 내 다양한 ​​시간의 기지는 FFmpeg의 출력 결과와 일치하지 않는 것이다. 특히, 내 출력의 TBC는 출력 코덱 컨텍스트의 타임베이스의 2 배가되는 것 같습니다. Gif 파일 형식의 문제인 경우 출력 코덱 컨텍스트가 항상 1/100로 설정되어있는 것 같습니다.

비트 레이트 계산과 나는이 모든 문제를 내 출력의 점에 /의 DTS 값이 일치하더라도, 제대로 내 PTS/DTS를 설정하지 않는 나에게 관련 될 수 있다는 것을 직감을 가지고

int calculated_br = istream_codec_context->time_base.den *  
        avpicture_get_size(AV_PIX_FMT_YUV420P, ostream_codec_context->width, 
             ostream_codec_context->height);  

ostream_codec_context->bit_rate = calculated_br; 
ostream_codec_context->rc_min_rate = calculated_br; 
ostream_codec_context->rc_max_rate = calculated_br; 
ostream_codec_context->rc_buffer_size = calculated_br; 

설정 FFmpeg의 출력.

도와 주셔서 감사합니다. 감사합니다!

답변

0

출력에 libx264를 사용하면 this answer에 설명 된대로 시간 소인을 수동으로 조정해야 할 수 있습니다. 이것은 귀하의 비트 전송률 문제를 설명 할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 불행히도 해당 게시물의 솔루션으로 내 문제가 해결되지 않았습니다.내 pts 및 dts 내 코덱 컨텍스트 timebases 및 스트림 timebases 사용하여 rescaling 시도했지만 실제로 내 출력 재생 속도를 엉망으로. 인코딩 후에 pts와 dts를 재조정하지 않으면 적절한 속도로 재생되는 비디오를 얻을 수 있다는 점이 약간 재미 있습니다. – Roman