c++ - libvlc ffmpeg: No seek in mpegts h264 stream -
i using ffmpeg record video input gdi (windows screen recorder) view later using vlc (via activex plugin) + ffmpeg decode it.
right seeking in video not working in vlc via plugin (which critical). vlc player provide seeking, more byte position seeking (on i- frames larger other frames makes larger steps on horizontal scroll , there no timestamps).
encoder opened next defaults:
avformat_alloc_output_context2(&outputcontext, null, "mpegts", "test.mpg"); outputformat = outputcontext->oformat; encoder = avcodec_find_encoder(av_codec_id_h264); outputstream = avformat_new_stream(outputcontext, encoder); outputstream->id = outputcontext->nb_streams - 1; encodercontext = outputstream->codec; encodercontext->bit_rate = bitrate; // 800000 default encodercontext->rc_max_rate = bitrate; encodercontext->width = imagewidth; // 1920 encodercontext->height = imageheight; // 1080 encodercontext->time_base.num = 1; encodercontext->time_base.den = fps; // 25 default encodercontext->gop_size = fps; encodercontext->keyint_min = fps; encodercontext->max_b_frames = 0; encodercontext->pix_fmt = av_pix_fmt_yuv420p; outputstream->time_base = encodercontext->time_base; avcodec_open2(encodercontext, encoder, null);
recording done way:
// impl of gdi recorder, returning avframe data , linesize filled. avframe* tmp_frame = impl_->recorder->acquireframe(); // converting rgb -> yuv420 sws_scale(impl_->scalecontext, tmp_frame->data, tmp_frame->linesize, 0, impl_->frame->height, impl_->frame->data, impl_->frame->linesize); // pts variable calculated using queryperformancecounter form winapi. strictly increasing impl_->frame->pts = pts; avcodec_encode_video2(impl_->encodercontext, impl_->packet, impl_->frame, &out_size); if (out_size) { impl_->packet->pts = pts; impl_->packet->dts = pts; impl_->packet->duration = 1; // here is! set has no effect av_packet_rescale_ts(impl_->packet, impl_->encodercontext->time_base, impl_->outputstream->time_base); // here pts = 3600*pts, dts = 3600*pts, duration = 3600 consider legit in terms of milliseconds impl_->packet->stream_index = impl_->outputstream->index; av_interleaved_write_frame(impl_->outputcontext, impl_->packet); av_packet_unref(impl_->packet); out_size = 0; }
ffprobe providing next info on frames:
[frame] media_type=video stream_index=0 key_frame=1 pkt_pts=3600 pkt_pts_time=0:00:00.040000 pkt_dts=3600 pkt_dts_time=0:00:00.040000 best_effort_timestamp=3600 best_effort_timestamp_time=0:00:00.040000 pkt_duration=n/a pkt_duration_time=n/a pkt_pos=564 pkt_size=97.018555 kibyte width=1920 height=1080 pix_fmt=yuv420p sample_aspect_ratio=n/a pict_type=i coded_picture_number=0 display_picture_number=0 interlaced_frame=0 top_field_first=0 repeat_pict=0 [/frame]
i believe problem in pkt_duration
variable, though set. doing wrong in recording can't seek in video?
p.s. on other videos (also h264) seeking working in activex vlc plugin.
what wrong, is:
impl_->packet->pts = pts; impl_->packet->dts = pts;
pts , dts not equal! if have i-frames, not case here. also, comment says: pts variable calculated using queryperformancecounter
form winapi. if frame rate constant, , believe is, don't need queryperformancecounter
api. pts in 90khz units. duration of 1 frame expressed in 90khz calculated this:
90000 x denominator / numerator
if fps 25 numerator 25 , denominator 1. 29.97 fps numerator 30000 , denominator 1001. each new frame's pts should increased amount (unless have dropped frames). regarding dts, encoder should provide value.
Comments
Post a Comment