Replace av_init_packet in FFmpeg 3.2+ (#784)

This commit is contained in:
Frank Dana
2022-03-16 23:58:06 -04:00
committed by GitHub
parent aee76211ac
commit 08b4975600

View File

@@ -856,16 +856,20 @@ void FFmpegWriter::flush_encoders() {
#endif
// FLUSH VIDEO ENCODER
if (info.has_video)
if (info.has_video) {
for (;;) {
// Increment PTS (in frames and scaled to the codec's timebase)
video_timestamp += 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);
pkt.data = NULL;
pkt.size = 0;
#if IS_FFMPEG_3_2
AVPacket* pkt = av_packet_alloc();
#else
AVPacket* pkt;
av_init_packet(pkt);
#endif
pkt->data = NULL;
pkt->size = 0;
/* encode the image */
int got_packet = 0;
@@ -876,21 +880,21 @@ void FFmpegWriter::flush_encoders() {
error_code = avcodec_send_frame(video_codec_ctx, NULL);
got_packet = 0;
while (error_code >= 0) {
error_code = avcodec_receive_packet(video_codec_ctx, &pkt);
error_code = avcodec_receive_packet(video_codec_ctx, pkt);
if (error_code == AVERROR(EAGAIN)|| error_code == AVERROR_EOF) {
got_packet = 0;
// Write packet
avcodec_flush_buffers(video_codec_ctx);
break;
}
av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
pkt.stream_index = video_st->index;
error_code = av_interleaved_write_frame(oc, &pkt);
av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
pkt->stream_index = video_st->index;
error_code = av_interleaved_write_frame(oc, pkt);
}
#else // IS_FFMPEG_3_2
// Encode video packet (older than FFmpeg 3.2)
error_code = avcodec_encode_video2(video_codec_ctx, &pkt, NULL, &got_packet);
error_code = avcodec_encode_video2(video_codec_ctx, pkt, NULL, &got_packet);
#endif // IS_FFMPEG_3_2
@@ -905,11 +909,11 @@ void FFmpegWriter::flush_encoders() {
}
// set the timestamp
av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
pkt.stream_index = video_st->index;
av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
pkt->stream_index = video_st->index;
// Write packet
error_code = av_interleaved_write_frame(oc, &pkt);
error_code = av_interleaved_write_frame(oc, pkt);
if (error_code < 0) {
ZmqLogger::Instance()->AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR ["
@@ -917,15 +921,20 @@ void FFmpegWriter::flush_encoders() {
"error_code", error_code);
}
}
}
// FLUSH AUDIO ENCODER
if (info.has_audio) {
for (;;) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
pkt.pts = pkt.dts = audio_timestamp;
#if IS_FFMPEG_3_2
AVPacket* pkt = av_packet_alloc();
#else
AVPacket* pkt;
av_init_packet(pkt);
#endif
pkt->data = NULL;
pkt->size = 0;
pkt->pts = pkt->dts = audio_timestamp;
/* encode the image */
int error_code = 0;
@@ -933,7 +942,7 @@ void FFmpegWriter::flush_encoders() {
#if IS_FFMPEG_3_2
error_code = avcodec_send_frame(audio_codec_ctx, NULL);
#else
error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, NULL, &got_packet);
error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, NULL, &got_packet);
#endif
if (error_code < 0) {
ZmqLogger::Instance()->AppendDebugMethod(
@@ -947,17 +956,17 @@ 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 = audio_timestamp;
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);
av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
// set stream
pkt.stream_index = audio_st->index;
pkt.flags |= AV_PKT_FLAG_KEY;
pkt->stream_index = audio_st->index;
pkt->flags |= AV_PKT_FLAG_KEY;
// Write packet
error_code = av_interleaved_write_frame(oc, &pkt);
error_code = av_interleaved_write_frame(oc, pkt);
if (error_code < 0) {
ZmqLogger::Instance()->AppendDebugMethod(
"FFmpegWriter::flush_encoders ERROR ["
@@ -966,10 +975,10 @@ void FFmpegWriter::flush_encoders() {
}
// Increment PTS by duration of packet
audio_timestamp += pkt.duration;
audio_timestamp += pkt->duration;
// deallocate memory for packet
AV_FREE_PACKET(&pkt);
AV_FREE_PACKET(pkt);
}
}
@@ -1035,8 +1044,8 @@ void FFmpegWriter::Close() {
}
// Reset frame counters
video_timestamp = 0;
audio_timestamp = 0;
video_timestamp = 0;
audio_timestamp = 0;
// Free the context which frees the streams too
avformat_free_context(oc);
@@ -1920,13 +1929,17 @@ void FFmpegWriter::write_audio_packets(bool is_final) {
frame_final->pts = audio_timestamp;
// Init the packet
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = audio_encoder_buffer;
pkt.size = audio_encoder_buffer_size;
#if IS_FFMPEG_3_2
AVPacket* pkt = av_packet_alloc();
#else
AVPacket* pkt;
av_init_packet(pkt);
#endif
pkt->data = audio_encoder_buffer;
pkt->size = audio_encoder_buffer_size;
// Set the packet's PTS prior to encoding
pkt.pts = pkt.dts = audio_timestamp;
pkt->pts = pkt->dts = audio_timestamp;
/* encode the audio samples */
int got_packet_ptr = 0;
@@ -1942,8 +1955,8 @@ void FFmpegWriter::write_audio_packets(bool is_final) {
}
else {
if (ret >= 0)
pkt.size = 0;
ret = avcodec_receive_packet(audio_codec_ctx, &pkt);
pkt->size = 0;
ret = avcodec_receive_packet(audio_codec_ctx, pkt);
if (ret >= 0)
frame_finished = 1;
if(ret == AVERROR(EINVAL) || ret == AVERROR_EOF) {
@@ -1954,31 +1967,31 @@ void FFmpegWriter::write_audio_packets(bool is_final) {
ret = frame_finished;
}
}
if (!pkt.data && !frame_finished)
if (!pkt->data && !frame_finished)
{
ret = -1;
}
got_packet_ptr = ret;
#else
// Encode audio (older versions of FFmpeg)
int error_code = avcodec_encode_audio2(audio_codec_ctx, &pkt, frame_final, &got_packet_ptr);
int error_code = avcodec_encode_audio2(audio_codec_ctx, pkt, frame_final, &got_packet_ptr);
#endif
/* if zero size, it means the image was buffered */
if (error_code == 0 && got_packet_ptr) {
// 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 = audio_timestamp;
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);
av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_st->time_base);
// set stream
pkt.stream_index = audio_st->index;
pkt.flags |= AV_PKT_FLAG_KEY;
pkt->stream_index = audio_st->index;
pkt->flags |= AV_PKT_FLAG_KEY;
/* write the compressed frame in the media file */
error_code = av_interleaved_write_frame(oc, &pkt);
error_code = av_interleaved_write_frame(oc, pkt);
}
if (error_code < 0) {
@@ -1996,7 +2009,7 @@ void FFmpegWriter::write_audio_packets(bool is_final) {
AV_FREE_FRAME(&frame_final);
// deallocate memory for packet
AV_FREE_PACKET(&pkt);
AV_FREE_PACKET(pkt);
// Reset position
audio_input_position = 0;
@@ -2044,23 +2057,23 @@ AVFrame *FFmpegWriter::allocate_avframe(PixelFormat pix_fmt, int width, int heig
// process video frame
void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
// Determine the height & width of the source image
int source_image_width = frame->GetWidth();
int source_image_height = frame->GetHeight();
// Determine the height & width of the source image
int source_image_width = frame->GetWidth();
int source_image_height = frame->GetHeight();
// Do nothing if size is 1x1 (i.e. no image in this frame)
if (source_image_height == 1 && source_image_width == 1)
return;
// Do nothing if size is 1x1 (i.e. no image in this frame)
if (source_image_height == 1 && source_image_width == 1)
return;
// Init rescalers (if not initialized yet)
if (image_rescalers.size() == 0)
InitScalers(source_image_width, source_image_height);
// Init rescalers (if not initialized yet)
if (image_rescalers.size() == 0)
InitScalers(source_image_width, source_image_height);
// Get a unique rescaler (for this thread)
SwsContext *scaler = image_rescalers[rescaler_position];
rescaler_position++;
if (rescaler_position == num_of_rescalers)
rescaler_position = 0;
// Get a unique rescaler (for this thread)
SwsContext *scaler = image_rescalers[rescaler_position];
rescaler_position++;
if (rescaler_position == num_of_rescalers)
rescaler_position = 0;
// Allocate an RGB frame & final output frame
int bytes_source = 0;
@@ -2131,8 +2144,14 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
#endif
// Raw video case.
#if IS_FFMPEG_3_2
AVPacket* pkt = av_packet_alloc();
#else
AVPacket* pkt;
av_packet_from_data(
av_init_packet(pkt);
#endif
av_packet_from_data(
pkt, frame_final->data[0],
frame_final->linesize[0] * frame_final->height);
@@ -2158,11 +2177,15 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
} else
{
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
pkt.pts = pkt.dts = AV_NOPTS_VALUE;
#if IS_FFMPEG_3_2
AVPacket* pkt = av_packet_alloc();
#else
AVPacket* pkt;
av_init_packet(pkt);
#endif
pkt->data = NULL;
pkt->size = 0;
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
// Assign the initial AVFrame PTS from the frame counter
frame_final->pts = video_timestamp;
@@ -2188,12 +2211,12 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
int got_packet_ptr = 0;
int error_code = 0;
#if IS_FFMPEG_3_2
// Write video packet (latest version of FFmpeg)
// Write video packet
int ret;
#if USE_HW_ACCEL
if (hw_en_on && hw_en_supported) {
ret = avcodec_send_frame(video_codec_ctx, hw_frame); //hw_frame!!!
ret = avcodec_send_frame(video_codec_ctx, hw_frame); //hw_frame!!!
} else
#endif // USE_HW_ACCEL
{
@@ -2213,7 +2236,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
}
else {
while (ret >= 0) {
ret = avcodec_receive_packet(video_codec_ctx, &pkt);
ret = avcodec_receive_packet(video_codec_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
avcodec_flush_buffers(video_codec_ctx);
@@ -2228,7 +2251,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
}
#else
// Write video packet (older than FFmpeg 3.2)
error_code = avcodec_encode_video2(video_codec_ctx, &pkt, frame_final, &got_packet_ptr);
error_code = avcodec_encode_video2(video_codec_ctx, pkt, frame_final, &got_packet_ptr);
if (error_code != 0) {
ZmqLogger::Instance()->AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR ["
@@ -2244,11 +2267,11 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
/* if zero size, it means the image was buffered */
if (error_code == 0 && got_packet_ptr) {
// set the timestamp
av_packet_rescale_ts(&pkt, video_codec_ctx->time_base, video_st->time_base);
pkt.stream_index = video_st->index;
av_packet_rescale_ts(pkt, video_codec_ctx->time_base, video_st->time_base);
pkt->stream_index = video_st->index;
/* write the compressed frame in the media file */
int result = av_interleaved_write_frame(oc, &pkt);
int result = av_interleaved_write_frame(oc, pkt);
if (result < 0) {
ZmqLogger::Instance()->AppendDebugMethod(
"FFmpegWriter::write_video_packet ERROR ["
@@ -2259,7 +2282,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
}
// Deallocate packet
AV_FREE_PACKET(&pkt);
AV_FREE_PACKET(pkt);
#if USE_HW_ACCEL
if (hw_en_on && hw_en_supported) {
if (hw_frame) {
@@ -2270,8 +2293,8 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
#endif // USE_HW_ACCEL
}
// Increment PTS (in frames and scaled to the codec's timebase)
video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
// Increment PTS (in frames and scaled to the codec's timebase)
video_timestamp += av_rescale_q(1, av_make_q(info.fps.den, info.fps.num), video_codec_ctx->time_base);
// Success
return true;