in src/guacenc/ffmpeg-compat.c [101:214]
int guacenc_avcodec_encode_video(guacenc_video* video, AVFrame* frame) {
/* For libavcodec < 54.1.0: packets were handled as raw malloc'd buffers */
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,1,0)
AVCodecContext* context = video->context;
/* Calculate appropriate buffer size */
int length = FF_MIN_BUFFER_SIZE + 12 * context->width * context->height;
/* Allocate space for output */
uint8_t* data = malloc(length);
if (data == NULL)
return -1;
/* Encode packet of video data */
int used = avcodec_encode_video(context, data, length, frame);
if (used < 0) {
guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64,
video->next_pts);
free(data);
return -1;
}
/* Report if no data needs to be written */
if (used == 0) {
free(data);
return 0;
}
/* Write data, logging any errors */
guacenc_write_packet(video, data, used);
free(data);
return 1;
#else
/* For libavcodec < 57.37.100: input/output was not decoupled and static
* allocation of AVPacket was supported.
*
* NOTE: Since dynamic allocation of AVPacket was added before this point (in
* 57.12.100) and static allocation was deprecated later (in 58.133.100), it is
* convenient to tie static vs. dynamic allocation to the old vs. new I/O
* mechanism and avoid further complicating the version comparison logic. */
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100)
/* Init video packet */
AVPacket packet;
av_init_packet(&packet);
/* Request that encoder allocate data for packet */
packet.data = NULL;
packet.size = 0;
/* Write frame to video */
int got_data;
if (avcodec_encode_video2(video->context, &packet, frame, &got_data) < 0) {
guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64,
video->next_pts);
return -1;
}
/* Write corresponding data to file */
if (got_data) {
guacenc_write_packet(video, (void*) &packet, packet.size);
av_packet_unref(&packet);
}
#else
/* Write frame to video */
int result = avcodec_send_frame(video->context, frame);
/* Stop once encoded has been flushed */
if (result == AVERROR_EOF)
return 0;
/* Abort on error */
else if (result < 0) {
guacenc_log(GUAC_LOG_WARNING, "Error encoding frame #%" PRId64,
video->next_pts);
return -1;
}
AVPacket* packet = av_packet_alloc();
if (packet == NULL)
return -1;
/* Flush all available packets */
int got_data = 0;
while (avcodec_receive_packet(video->context, packet) == 0) {
/* Data was received */
got_data = 1;
/* Attempt to write data to output file */
guacenc_write_packet(video, (void*) packet, packet->size);
av_packet_unref(packet);
}
av_packet_free(&packet);
#endif
/* Frame may have been queued for later writing / reordering */
if (!got_data)
guacenc_log(GUAC_LOG_DEBUG, "Frame #%08" PRId64 ": queued for later",
video->next_pts);
return got_data;
#endif
}