2016-07-25 32 views
0

私はGIF(Windowsのスクリーンレコーダー)からのビデオ入力を記録するためにffmpegを使用して、VLC(ActiveXプラグイン経由)+ ffmpegを使用してそれを表示します。libvlc ffmpeg:mpegts h264ストリームでシークなし

現在ビデオでの検索は、VLC経由でVLCで動作していません(これは重要です)。 VLCプレーヤー自体はシークを提供しますが、それはバイト位置のシークによく似ています(他のフレームより大きいIフレームでは、水平スクロールで大きなステップを作成し、タイムスタンプもありません)。

エンコーダは、次のデフォルトで開かれます。

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 by 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 by 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); 

記録はこのように行われている:私はその問題を信じる

[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] 

// my impl of GDI recorder, returning AVFrame with only data and 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 is calculated by using QueryPerformanceCounter form WinAPI. It is 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 it is! It is set but 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 what I consider to be 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は、フレーム上の次の情報を提供しています変数はpkt_durationですが、設定されていました。 私は録画に間違っているので、ビデオでは探していないのですか?

P.S.他のビデオ(またh264)での検索は、ActiveX VLCプラグインで動作しています。確かに間違っている何

答えて

0

は、次のとおりです。

impl_->packet->pts = pts; 
impl_->packet->dts = pts; 

PTSとDTSが等しくありません!あなたがIフレームだけを持っているのであれば、そうではないかもしれません。また、あなたのコメントは言う:pts変数QueryPerformanceCounterフォームWinAPIを使用して計算されます。あなたのフレームレートが一定で、私がそれが信じているならば、あなたはQueryPerformanceCounter APIを必要としません。 PTSは通常90kHz単位です。 1つのフレームの期間た90KHzで発現がこのように計算される:FPSが25である場合、分子は25と分母である

90000 X分母/分子

29.97 1.される分子は、30000であり、FPS分母は1001です。新しいフレームのそれぞれのPTSは、その分だけ増やす必要があります(フレームを落とさない限り)。 DTSに関して、エンコーダはその値を提供すべきである。

+0

あなたの答えをありがとう! なぜIフレームとPフレームしか持たない場合、PTSとDTSが等しくないのですか? Iフレームは明白です。しかし、Pフレームもデコードされ、どのように格納されるかが示されなければならない。または私は間違っていますか? 「QueryPerformanceCounter」について私はそれを使用して一定のFPSを維持しながら、画面をつかんでいます(さまざまなシステム負荷を使って、できるだけ希望のfpsに近づけるようにスリープ時間を変更します)。 PTSの計算方法。私は90kHzの定数で完全に失われています。現在、PTSはフレームごとに1ずつ増加すると計算されます。私は 'av_packet_rescale_ts'が私のために他のすべてを計算すると信じていました。 – ElDorado

+0

計算されたPTSと継続時間(3600、コード・コメンテートとffprobe出力を参照)私は90kHzのタイミングに関してさらに合理的であると考えます。しかし、ffprobeの出力でフレーム時間が計算されないのはなぜですか? – ElDorado

+0

あなたの答えをありがとう! 私はビデオでVLCを探すことができました。なぜそれが他のビデオにも役立つのか分からないが、2.2.4にアップデートするとそれは私の作品にも当てはまる。 – ElDorado

関連する問題