diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 845c1099..92e9f8fa 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -84,7 +84,7 @@ FFmpegWriter::FFmpegWriter(const std::string& path) : path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL), audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0), initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32), - rescaler_position(0), video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), write_video_count(0), write_audio_count(0), + rescaler_position(0), video_codec_ctx(NULL), audio_codec_ctx(NULL), is_writing(false), video_timestamp(0), audio_timestamp(0), original_sample_rate(0), original_channels(0), avr(NULL), avr_planar(NULL), is_open(false), prepare_streams(false), write_header(false), write_trailer(false), audio_encoder_buffer_size(0), audio_encoder_buffer(NULL) { @@ -847,7 +847,7 @@ void FFmpegWriter::flush_encoders() { for (;;) { // Increment PTS (in frames and scaled to the codec's timebase) - write_video_count += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base); + video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base); AVPacket pkt; av_init_packet(&pkt); @@ -906,7 +906,7 @@ void FFmpegWriter::flush_encoders() { av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; - pkt.pts = pkt.dts = write_audio_count; + pkt.pts = pkt.dts = audio_timestamp; /* encode the image */ int error_code = 0; @@ -927,7 +927,7 @@ void FFmpegWriter::flush_encoders() { // Since the PTS can change during encoding, set the value again. This seems like a huge hack, // but it fixes lots of PTS related issues when I do this. - pkt.pts = pkt.dts = write_audio_count; + pkt.pts = pkt.dts = audio_timestamp; // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase) av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base); @@ -944,13 +944,12 @@ void FFmpegWriter::flush_encoders() { "error_code", error_code); } - // deallocate memory for packet + // Increment PTS by duration of packet + audio_timestamp += pkt.duration; + + // deallocate memory for packet AV_FREE_PACKET(&pkt); } - - // Increment PTS (in samples and scaled to the codec's timebase) - // for some reason, it requires me to multiply channels X 2 - write_audio_count += av_rescale_q(audio_input_position / (audio_codec_ctx->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)), av_make_q(1, info.sample_rate), audio_codec_ctx->time_base); } } @@ -1015,8 +1014,8 @@ void FFmpegWriter::Close() { } // Reset frame counters - write_video_count = 0; - write_audio_count = 0; + video_timestamp = 0; + audio_timestamp = 0; // Free the context which frees the streams too avformat_free_context(oc); @@ -1818,7 +1817,7 @@ void FFmpegWriter::write_audio_packets(bool is_final) { } // Set the AVFrame's PTS - frame_final->pts = write_audio_count; + frame_final->pts = audio_timestamp; // Init the packet AVPacket pkt; @@ -1827,7 +1826,7 @@ void FFmpegWriter::write_audio_packets(bool is_final) { pkt.size = audio_encoder_buffer_size; // Set the packet's PTS prior to encoding - pkt.pts = pkt.dts = write_audio_count; + pkt.pts = pkt.dts = audio_timestamp; /* encode the audio samples */ int got_packet_ptr = 0; @@ -1869,7 +1868,7 @@ void FFmpegWriter::write_audio_packets(bool is_final) { // Since the PTS can change during encoding, set the value again. This seems like a huge hack, // but it fixes lots of PTS related issues when I do this. - pkt.pts = pkt.dts = write_audio_count; + pkt.pts = pkt.dts = audio_timestamp; // Scale the PTS to the audio stream timebase (which is sometimes different than the codec's timebase) av_packet_rescale_ts(&pkt, audio_codec_ctx->time_base, audio_st->time_base); @@ -1886,8 +1885,8 @@ void FFmpegWriter::write_audio_packets(bool is_final) { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (std::string) av_err2str(error_code) + "]", "error_code", error_code); } - // Increment PTS - write_audio_count += FFMIN(audio_input_frame_size, audio_input_position); + // Increment PTS by duration of packet + audio_timestamp += pkt.duration; // deallocate AVFrame av_freep(&(frame_final->data[0])); @@ -2028,7 +2027,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra pkt.size = sizeof(AVPicture); // Set PTS (in frames and scaled to the codec's timebase) - pkt.pts = write_video_count; + pkt.pts = video_timestamp; /* write the compressed frame in the media file */ int error_code = av_interleaved_write_frame(oc, &pkt); @@ -2050,7 +2049,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra pkt.pts = pkt.dts = AV_NOPTS_VALUE; // Assign the initial AVFrame PTS from the frame counter - frame_final->pts = write_video_count; + frame_final->pts = video_timestamp; #if USE_HW_ACCEL if (hw_en_on && hw_en_supported) { if (!(hw_frame = av_frame_alloc())) { @@ -2135,6 +2134,9 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra } } + // Increment PTS (in frames and scaled to the codec's timebase) + video_timestamp += pkt.duration; + // Deallocate packet AV_FREE_PACKET(&pkt); #if USE_HW_ACCEL @@ -2147,9 +2149,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra #endif // USE_HW_ACCEL } - // Increment PTS (in frames and scaled to the codec's timebase) - write_video_count += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base); - // Success return true; } diff --git a/src/FFmpegWriter.h b/src/FFmpegWriter.h index 44f7cb35..79564b5c 100644 --- a/src/FFmpegWriter.h +++ b/src/FFmpegWriter.h @@ -151,8 +151,8 @@ namespace openshot { int cache_size; bool is_writing; bool is_open; - int64_t write_video_count; - int64_t write_audio_count; + int64_t video_timestamp; + int64_t audio_timestamp; bool prepare_streams; bool write_header;