프레임별로 비디오 프레임을 트랜스 코딩하고 x264 + ffmpeg를 사용하여 인코딩합니다. 원본 비디오는 정상적으로 재생되지만 트랜스 코딩 된 비디오의 처음 몇 프레임에는 회색 인공물이 표시됩니다. 나는 이것이 시간 압축 때문이라고 이해하고 있으며, 이러한 인공물은 몇 프레임 후에 사라진다.비디오 인코딩 및 키 프레임
첫 번째와 두 번째 프레임 인이 두 그림을 참조하십시오. 세 번째 프레임 (즉, 아무 회색 인공물과 두 번째처럼 흐릿하지 않음) 내가 키 프레임을 할 첫 번째 프레임을 강제 할 방법
(완전 내 출력 비디오로 인코딩되지 즉)이되도록 정상 공예품이 보이지 않습니까?
편집 - 자세한 내용은 여기
나는 세부 사항에서 더 많은 일을하고있는 무슨이다. 비트 형식 차이 튜토리얼을 사용하여 프레임별로 비디오 프레임을 읽고 각 프레임을 새 비디오로 다시 인코딩했습니다. 내 인코딩 매개 변수는 다음과 같습니다.
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;
}
ffmpeg 명령과 전체 콘솔 출력을 표시하지 않으면 우리는 추측 할 수 있습니다. – LordNeckbeard