Note that there are some explanatory texts on larger screens.

plurals
  1. POVideo encoding and keyframes
    text
    copied!<p>I am transcoding a video frame by frame and using x264+ffmpeg to encode. The original video plays fine, but the first few frames of my transcoded vide show grey artefacts. I understand this is because of time compression and these artefacts disappear after a few frames. </p> <p>See these two pictures which are the first and second frames. The third frame is normal (i.e. no grey artefact and not blurry like the second one) <img src="https://i.stack.imgur.com/YmhPz.png" alt="First frame"> <img src="https://i.stack.imgur.com/MQTGJ.png" alt="Second frame"></p> <p>How can I force the first frame to be a key frame (ie fully encoded in my output video) so that these artefacts do not show?</p> <p><strong>Edit - more details</strong></p> <p>Here is what I am doing more in details. I used bit form differents tutorials to read a video frame by frame and reencode each frame to a new video. My encoding parameters are the following:</p> <pre><code>avcodec_get_context_defaults3(c, *codec); c-&gt;codec_id = codec_id; c-&gt;bit_rate = output_bitrate; /* Resolution must be a multiple of two. */ c-&gt;width = output_width; c-&gt;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-&gt;r_frame_rate.num = output_framerate_num; st-&gt;r_frame_rate.den = output_framerate_den; c-&gt;time_base.den = output_timebase_den; c-&gt;time_base.num = output_timebase_num; c-&gt;gop_size = 3; /* emit one intra frame every twelve frames at most */ c-&gt;pix_fmt = STREAM_PIX_FMT; if (c-&gt;codec_id == AV_CODEC_ID_MPEG2VIDEO) { /* just for testing, we also add B frames */ c-&gt;max_b_frames = 2; } if (c-&gt;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-&gt;mb_decision = 2; } c-&gt;max_b_frames = 2; c-&gt;scenechange_threshold = 0; c-&gt;rc_buffer_size = 0; c-&gt;me_method = ME_ZERO; </code></pre> <p>Then I process each frame, probably doing something wrong there. The decoding bit:</p> <pre><code>while(av_read_frame(gFormatCtx, &amp;packet)&gt;=0) { // Is this a packet from the video stream? if(packet.stream_index==gVideoStreamIndex) { // Decode video frame avcodec_decode_video2(gVideoCodecCtx, pCurrentFrame, &amp;frameFinished, &amp;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-&gt;streams[gVideoStreamIndex]-&gt;time_base); [...] muxing_writeVideoFrame(pCurrentFrame, packet.pts); } } } </code></pre> <p>The actual writing:</p> <pre><code>int muxing_writeVideoFrame(AVFrame *frame, int64_t pts) { frameCount = frameCount +1; if(frameCount &gt; 0) { if (video_st) video_pts = (double)video_st-&gt;pts.val * video_st-&gt;time_base.num / video_st-&gt;time_base.den; else video_pts = 0.0; if (video_st &amp;&amp; !(video_st &amp;&amp; audio_st &amp;&amp; audio_pts &lt; video_pts)) { frame-&gt;pts = pts;//av_rescale_q(frame_count, video_st-&gt;codec-&gt;time_base, video_st-&gt;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-&gt;codec; /* encode the image */ AVPacket pkt; int got_output; av_init_packet(&amp;pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; ret = avcodec_encode_video2(c, &amp;pkt, frame, &amp;got_output); if (ret &lt; 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-&gt;coded_frame-&gt;key_frame) pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = st-&gt;index; /* Write the compressed frame to the media file. */ ret = av_interleaved_write_frame(oc, &amp;pkt); } else { ret = 0; } if (ret != 0) { LOGI(10, av_err2str(ret)); exit(1); } frame_count++; return got_output; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload