2013-02-03 4 views
4

프레임별로 비디오 프레임을 트랜스 코딩하고 x264 + ffmpeg를 사용하여 인코딩합니다. 원본 비디오는 정상적으로 재생되지만 트랜스 코딩 된 비디오의 처음 몇 프레임에는 회색 인공물이 표시됩니다. 나는 이것이 시간 압축 때문이라고 이해하고 있으며, 이러한 인공물은 몇 프레임 후에 사라진다.비디오 인코딩 및 키 프레임

첫 번째와 두 번째 프레임 인이 두 그림을 참조하십시오. 세 번째 프레임 (즉, 아무 회색 인공물과 두 번째처럼 흐릿하지 않음) 내가 키 프레임을 할 첫 번째 프레임을 강제 할 방법 First frame Second frame

(완전 내 출력 비디오로 인코딩되지 즉)이되도록 정상 공예품이 보이지 않습니까?

편집 - 자세한 내용은 여기

나는 세부 사항에서 더 많은 일을하고있는 무슨이다. 비트 형식 차이 튜토리얼을 사용하여 프레임별로 비디오 프레임을 읽고 각 프레임을 새 비디오로 다시 인코딩했습니다. 내 인코딩 매개 변수는 다음과 같습니다.

avcodec_get_context_defaults3(c, *codec); 
c->codec_id = codec_id; 
c->bit_rate = output_bitrate; 
/* Resolution must be a multiple of two. */ 
c->width = output_width; 
c->height = output_height; 
/* timebase: This is the fundamental unit of time (in seconds) in terms 
* of which frame timestamps are represented. For fixed-fps content, 
* timebase should be 1/framerate and timestamp increments should be 
* identical to 1. */ 
st->r_frame_rate.num = output_framerate_num; 
st->r_frame_rate.den = output_framerate_den; 
c->time_base.den = output_timebase_den; 
c->time_base.num = output_timebase_num; 
c->gop_size  = 3; /* emit one intra frame every twelve frames at most */ 
c->pix_fmt  = STREAM_PIX_FMT; 
if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { 
    /* just for testing, we also add B frames */ 
    c->max_b_frames = 2; 
} 
if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) { 
    /* Needed to avoid using macroblocks in which some coeffs overflow. 
    * This does not happen with normal video, it just happens here as 
    * the motion of the chroma plane does not match the luma plane. */ 
    c->mb_decision = 2; 
} 
c->max_b_frames = 2; 
c->scenechange_threshold = 0; 
c->rc_buffer_size = 0; 
c->me_method = ME_ZERO; 

그런 다음 각 프레임을 처리합니다. 디코딩 비트 :

while(av_read_frame(gFormatCtx, &packet)>=0) { 
    // Is this a packet from the video stream? 
    if(packet.stream_index==gVideoStreamIndex) { 
     // Decode video frame 
     avcodec_decode_video2(gVideoCodecCtx, pCurrentFrame, &frameFinished, &packet); 
     // Did we get a video frame? 
     if(frameFinished) { 
      [...] 
      if(firstPts == -999) /*Initial value*/ 
       firstPts = packet.pts; 
      deltaPts = packet.pts - firstPts; 
      double seconds = deltaPts*av_q2d(gFormatCtx->streams[gVideoStreamIndex]->time_base); 
      [...] 
      muxing_writeVideoFrame(pCurrentFrame, packet.pts); 
     } 
    } 
} 

실제 쓰기 : 비디오는 keyframe로 시작하지 않기 때문에

int muxing_writeVideoFrame(AVFrame *frame, int64_t pts) 
{ 
frameCount = frameCount +1; 
if(frameCount > 0) 
{ 
    if (video_st) 
     video_pts = (double)video_st->pts.val * video_st->time_base.num/
        video_st->time_base.den; 
    else 
     video_pts = 0.0; 

    if (video_st && !(video_st && audio_st && audio_pts < video_pts)) 
    { 
     frame->pts = pts;//av_rescale_q(frame_count, video_st->codec->time_base, video_st->time_base); 
     write_video_frame(oc, video_st, frame); 
    } 
} 

return 0; 
} 

static int write_video_frame(AVFormatContext *oc, AVStream *st, AVFrame *frame) 
{ 
    int ret; 
    static struct SwsContext *sws_ctx; 
    //LOGI(10, frame_count); 
    AVCodecContext *c = st->codec; 

    /* encode the image */ 
    AVPacket pkt; 
    int got_output; 
    av_init_packet(&pkt); 
    pkt.data = NULL; // packet data will be allocated by the encoder 
    pkt.size = 0; 
ret = avcodec_encode_video2(c, &pkt, frame, &got_output); 
if (ret < 0) { 
    fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret)); 
    exit(1); 
} 
/* If size is zero, it means the image was buffered. */ 
if (got_output) { 
    if (c->coded_frame->key_frame) 
     pkt.flags |= AV_PKT_FLAG_KEY; 
    pkt.stream_index = st->index; 
    /* Write the compressed frame to the media file. */ 
    ret = av_interleaved_write_frame(oc, &pkt); 
} else { 
    ret = 0; 
} 

    if (ret != 0) { 
     LOGI(10, av_err2str(ret)); 
     exit(1); 
    } 
    frame_count++; 
    return got_output; 
} 
+0

ffmpeg 명령과 전체 콘솔 출력을 표시하지 않으면 우리는 추측 할 수 있습니다. – LordNeckbeard

답변

1

이다. 이 문제를 해결하기 위해 AviDemux을 사용합니다. 버전 2.6

  • MP4 먹서
  • MP4v2 먹서

및 키 프레임없이 시작 아마도 더 많은 지원 비디오와 함께 시작.

1

문제는 인코딩되지 않은 부분을 디코딩 할 때 발생합니다 (x264에서는 그러한 아티팩트를 생성 할 수 없음). 그리고 위에서 말했듯이, 키 프레임이 아닌 디코딩을 시작한 것처럼 보입니다 (또는 스트림이 공개 샵이고 첫 번째 B- 프레임을 삭제하지 않았을 수도 있음).

+1

이것을 확인하기 위해 디코딩 한 처음 10 개의 프레임을 버리려고했습니다. 이것은 트랜스 코딩 된 비디오에서 얻는 손상된 프레임의 수보다 훨씬 많습니다. 이것은 똑같은 결과를줍니다. 또한 디코딩 된 모든 프레임을 화면에 표시하려고 시도했는데 모양이 좋았습니다. 사물의 인코딩면에서 뭔가 잘못 됐음에 틀림 없습니다. – tishu

+0

작은 인코딩 된 샘플을 어딘가에 업로드하십시오. 하지만 난 여전히 문제를 해독하는 것 또는 x264 API를 잘못 사용한다고 생각합니다 (트랜스 코딩 체인 중간에 프레임이 깨져서 보내십시오). – nobody555

+0

답장을 보내 주셔서 감사합니다. 나는 [예제 원본 파일] (http://dl.free.fr/jazSYmaGF) (빨간색 상자에 "Valider et telecharger le fichier"를 선택)과 그 결과 [변환 된 파일] (http : // dl. free.fr/vf0MF8LZ5)이 유물을 보여줍니다. – tishu