obs-ffmpeg: Use av_packet_alloc instead of av_init_packet

sizeof(AVPacket) being a part of the public ABI is deprecated. once
av_init_packet() is removed, new packets will only be able to be
allocated with av_packet_alloc().
In ffmpeg-mux, ffmpeg-vaapi, and obs-ffmpeg-nvenc, AVPacket is allocated
at the initialization to avoid frequent allocation of AVPacket.

Includes changes to win-dshow.
This commit is contained in:
Norihiro Kamae 2022-01-08 19:02:42 +09:00 committed by Jim
parent 85addc3dac
commit ba68eda590
5 changed files with 159 additions and 129 deletions

View File

@ -119,6 +119,7 @@ struct ffmpeg_mux {
AVFormatContext *output; AVFormatContext *output;
AVStream *video_stream; AVStream *video_stream;
AVCodecContext *video_ctx; AVCodecContext *video_ctx;
AVPacket *packet;
struct audio_info *audio_infos; struct audio_info *audio_infos;
struct main_params params; struct main_params params;
struct audio_params *audio; struct audio_params *audio;
@ -181,6 +182,8 @@ static void ffmpeg_mux_free(struct ffmpeg_mux *ffm)
dstr_free(&ffm->params.printable_file); dstr_free(&ffm->params.printable_file);
av_packet_free(&ffm->packet);
memset(ffm, 0, sizeof(*ffm)); memset(ffm, 0, sizeof(*ffm));
} }
@ -717,6 +720,8 @@ static int ffmpeg_mux_init_internal(struct ffmpeg_mux *ffm, int argc,
if (!ffmpeg_mux_get_extra_data(ffm)) if (!ffmpeg_mux_get_extra_data(ffm))
return FFM_ERROR; return FFM_ERROR;
ffm->packet = av_packet_alloc();
/* ffmpeg does not have a way of telling what's supported /* ffmpeg does not have a way of telling what's supported
* for a given output format, so we try each possibility */ * for a given output format, so we try each possibility */
return ffmpeg_mux_init_context(ffm); return ffmpeg_mux_init_context(ffm);
@ -786,7 +791,6 @@ static inline bool ffmpeg_mux_packet(struct ffmpeg_mux *ffm, uint8_t *buf,
struct ffm_packet_info *info) struct ffm_packet_info *info)
{ {
int idx = get_index(ffm, info); int idx = get_index(ffm, info);
AVPacket packet = {0};
/* The muxer might not support video/audio, or multiple audio tracks */ /* The muxer might not support video/audio, or multiple audio tracks */
if (idx == -1) { if (idx == -1) {
@ -796,18 +800,16 @@ static inline bool ffmpeg_mux_packet(struct ffmpeg_mux *ffm, uint8_t *buf,
const AVRational codec_time_base = const AVRational codec_time_base =
get_codec_context(ffm, info)->time_base; get_codec_context(ffm, info)->time_base;
av_init_packet(&packet); ffm->packet->data = buf;
ffm->packet->size = (int)info->size;
packet.data = buf; ffm->packet->stream_index = idx;
packet.size = (int)info->size; ffm->packet->pts = rescale_ts(ffm, codec_time_base, info->pts, idx);
packet.stream_index = idx; ffm->packet->dts = rescale_ts(ffm, codec_time_base, info->dts, idx);
packet.pts = rescale_ts(ffm, codec_time_base, info->pts, idx);
packet.dts = rescale_ts(ffm, codec_time_base, info->dts, idx);
if (info->keyframe) if (info->keyframe)
packet.flags = AV_PKT_FLAG_KEY; ffm->packet->flags = AV_PKT_FLAG_KEY;
int ret = av_interleaved_write_frame(ffm->output, &packet); int ret = av_interleaved_write_frame(ffm->output, ffm->packet);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "av_interleaved_write_frame failed: %d: %s\n", fprintf(stderr, "av_interleaved_write_frame failed: %d: %s\n",

View File

@ -43,6 +43,8 @@ struct nvenc_encoder {
AVCodec *nvenc; AVCodec *nvenc;
AVCodecContext *context; AVCodecContext *context;
AVPacket *packet;
AVFrame *vframe; AVFrame *vframe;
DARRAY(uint8_t) buffer; DARRAY(uint8_t) buffer;
@ -163,6 +165,8 @@ static bool nvenc_init_codec(struct nvenc_encoder *enc, bool psycho_aq)
return false; return false;
} }
enc->packet = av_packet_alloc();
enc->initialized = true; enc->initialized = true;
return true; return true;
} }
@ -318,29 +322,33 @@ static bool nvenc_reconfigure(void *data, obs_data_t *settings)
return true; return true;
} }
static inline void flush_remaining_packets(struct nvenc_encoder *enc)
{
int r_pkt = 1;
while (r_pkt) {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
if (avcodec_receive_packet(enc->context, enc->packet) < 0)
break;
#else
if (avcodec_encode_video2(enc->context, enc->packet, NULL,
&r_pkt) < 0)
break;
#endif
if (r_pkt)
av_packet_unref(enc->packet);
}
}
static void nvenc_destroy(void *data) static void nvenc_destroy(void *data)
{ {
struct nvenc_encoder *enc = data; struct nvenc_encoder *enc = data;
if (enc->initialized) { if (enc->initialized)
AVPacket pkt = {0}; flush_remaining_packets(enc);
int r_pkt = 1;
while (r_pkt) {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
if (avcodec_receive_packet(enc->context, &pkt) < 0)
break;
#else
if (avcodec_encode_video2(enc->context, &pkt, NULL,
&r_pkt) < 0)
break;
#endif
if (r_pkt)
av_packet_unref(&pkt);
}
}
av_packet_free(&enc->packet);
avcodec_close(enc->context); avcodec_close(enc->context);
av_frame_unref(enc->vframe); av_frame_unref(enc->vframe);
av_frame_free(&enc->vframe); av_frame_free(&enc->vframe);
@ -436,26 +444,23 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
struct encoder_packet *packet, bool *received_packet) struct encoder_packet *packet, bool *received_packet)
{ {
struct nvenc_encoder *enc = data; struct nvenc_encoder *enc = data;
AVPacket av_pkt = {0};
int got_packet; int got_packet;
int ret; int ret;
av_init_packet(&av_pkt);
copy_data(enc->vframe, frame, enc->height, enc->context->pix_fmt); copy_data(enc->vframe, frame, enc->height, enc->context->pix_fmt);
enc->vframe->pts = frame->pts; enc->vframe->pts = frame->pts;
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101) #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
ret = avcodec_send_frame(enc->context, enc->vframe); ret = avcodec_send_frame(enc->context, enc->vframe);
if (ret == 0) if (ret == 0)
ret = avcodec_receive_packet(enc->context, &av_pkt); ret = avcodec_receive_packet(enc->context, enc->packet);
got_packet = (ret == 0); got_packet = (ret == 0);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
ret = 0; ret = 0;
#else #else
ret = avcodec_encode_video2(enc->context, &av_pkt, enc->vframe, ret = avcodec_encode_video2(enc->context, enc->packet, enc->vframe,
&got_packet); &got_packet);
#endif #endif
if (ret < 0) { if (ret < 0) {
@ -463,25 +468,27 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
return false; return false;
} }
if (got_packet && av_pkt.size) { if (got_packet && enc->packet->size) {
if (enc->first_packet) { if (enc->first_packet) {
uint8_t *new_packet; uint8_t *new_packet;
size_t size; size_t size;
enc->first_packet = false; enc->first_packet = false;
obs_extract_avc_headers(av_pkt.data, av_pkt.size, obs_extract_avc_headers(enc->packet->data,
&new_packet, &size, enc->packet->size, &new_packet,
&enc->header, &enc->header_size, &size, &enc->header,
&enc->sei, &enc->sei_size); &enc->header_size, &enc->sei,
&enc->sei_size);
da_copy_array(enc->buffer, new_packet, size); da_copy_array(enc->buffer, new_packet, size);
bfree(new_packet); bfree(new_packet);
} else { } else {
da_copy_array(enc->buffer, av_pkt.data, av_pkt.size); da_copy_array(enc->buffer, enc->packet->data,
enc->packet->size);
} }
packet->pts = av_pkt.pts; packet->pts = enc->packet->pts;
packet->dts = av_pkt.dts; packet->dts = enc->packet->dts;
packet->data = enc->buffer.array; packet->data = enc->buffer.array;
packet->size = enc->buffer.num; packet->size = enc->buffer.num;
packet->type = OBS_ENCODER_VIDEO; packet->type = OBS_ENCODER_VIDEO;
@ -491,7 +498,7 @@ static bool nvenc_encode(void *data, struct encoder_frame *frame,
*received_packet = false; *received_packet = false;
} }
av_packet_unref(&av_pkt); av_packet_unref(enc->packet);
return true; return true;
} }

View File

@ -48,7 +48,7 @@ struct ffmpeg_output {
os_sem_t *write_sem; os_sem_t *write_sem;
os_event_t *stop_event; os_event_t *stop_event;
DARRAY(AVPacket) packets; DARRAY(AVPacket *) packets;
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -740,11 +740,9 @@ static void receive_video(void *param, struct video_data *frame)
return; return;
AVCodecContext *context = data->video_ctx; AVCodecContext *context = data->video_ctx;
AVPacket packet = {0}; AVPacket *packet = NULL;
int ret = 0, got_packet; int ret = 0, got_packet;
av_init_packet(&packet);
if (!output->video_start_ts) if (!output->video_start_ts)
output->video_start_ts = frame->timestamp; output->video_start_ts = frame->timestamp;
if (!data->start_timestamp) if (!data->start_timestamp)
@ -766,15 +764,19 @@ static void receive_video(void *param, struct video_data *frame)
else else
copy_data(data->vframe, frame, context->height, copy_data(data->vframe, frame, context->height,
context->pix_fmt); context->pix_fmt);
packet = av_packet_alloc();
#if LIBAVFORMAT_VERSION_MAJOR < 58 #if LIBAVFORMAT_VERSION_MAJOR < 58
if (data->output->flags & AVFMT_RAWPICTURE) { if (data->output->flags & AVFMT_RAWPICTURE) {
packet.flags |= AV_PKT_FLAG_KEY; packet->flags |= AV_PKT_FLAG_KEY;
packet.stream_index = data->video->index; packet->stream_index = data->video->index;
packet.data = data->vframe->data[0]; packet->data = data->vframe->data[0];
packet.size = sizeof(AVPicture); packet->size = sizeof(AVPicture);
pthread_mutex_lock(&output->write_mutex); pthread_mutex_lock(&output->write_mutex);
da_push_back(output->packets, &packet); da_push_back(output->packets, &packet);
packet = NULL;
pthread_mutex_unlock(&output->write_mutex); pthread_mutex_unlock(&output->write_mutex);
os_sem_post(output->write_sem); os_sem_post(output->write_sem);
@ -784,15 +786,14 @@ static void receive_video(void *param, struct video_data *frame)
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101) #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
ret = avcodec_send_frame(context, data->vframe); ret = avcodec_send_frame(context, data->vframe);
if (ret == 0) if (ret == 0)
ret = avcodec_receive_packet(context, &packet); ret = avcodec_receive_packet(context, packet);
got_packet = (ret == 0); got_packet = (ret == 0);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
ret = 0; ret = 0;
#else #else
ret = avcodec_encode_video2(context, &packet, data->vframe, ret = avcodec_encode_video2(context, packet, data->vframe, &got_packet);
&got_packet);
#endif #endif
if (ret < 0) { if (ret < 0) {
blog(LOG_WARNING, blog(LOG_WARNING,
@ -800,20 +801,21 @@ static void receive_video(void *param, struct video_data *frame)
"video: %s", "video: %s",
av_err2str(ret)); av_err2str(ret));
//FIXME: stop the encode with an error //FIXME: stop the encode with an error
return; goto fail;
} }
if (!ret && got_packet && packet.size) { if (!ret && got_packet && packet->size) {
packet.pts = rescale_ts(packet.pts, context, packet->pts = rescale_ts(packet->pts, context,
data->video->time_base); data->video->time_base);
packet.dts = rescale_ts(packet.dts, context, packet->dts = rescale_ts(packet->dts, context,
data->video->time_base); data->video->time_base);
packet.duration = (int)av_rescale_q( packet->duration = (int)av_rescale_q(
packet.duration, context->time_base, packet->duration, context->time_base,
data->video->time_base); data->video->time_base);
pthread_mutex_lock(&output->write_mutex); pthread_mutex_lock(&output->write_mutex);
da_push_back(output->packets, &packet); da_push_back(output->packets, &packet);
packet = NULL;
pthread_mutex_unlock(&output->write_mutex); pthread_mutex_unlock(&output->write_mutex);
os_sem_post(output->write_sem); os_sem_post(output->write_sem);
} else { } else {
@ -829,6 +831,9 @@ static void receive_video(void *param, struct video_data *frame)
} }
data->total_frames++; data->total_frames++;
fail:
av_packet_free(&packet);
} }
static void encode_audio(struct ffmpeg_output *output, int idx, static void encode_audio(struct ffmpeg_output *output, int idx,
@ -836,7 +841,7 @@ static void encode_audio(struct ffmpeg_output *output, int idx,
{ {
struct ffmpeg_data *data = &output->ff_data; struct ffmpeg_data *data = &output->ff_data;
AVPacket packet = {0}; AVPacket *packet = NULL;
int ret, got_packet; int ret, got_packet;
size_t total_size = data->frame_size * block_size * context->channels; size_t total_size = data->frame_size * block_size * context->channels;
@ -860,42 +865,48 @@ static void encode_audio(struct ffmpeg_output *output, int idx,
data->total_samples[idx] += data->frame_size; data->total_samples[idx] += data->frame_size;
packet = av_packet_alloc();
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101) #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
ret = avcodec_send_frame(context, data->aframe[idx]); ret = avcodec_send_frame(context, data->aframe[idx]);
if (ret == 0) if (ret == 0)
ret = avcodec_receive_packet(context, &packet); ret = avcodec_receive_packet(context, packet);
got_packet = (ret == 0); got_packet = (ret == 0);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
ret = 0; ret = 0;
#else #else
ret = avcodec_encode_audio2(context, &packet, data->aframe[idx], ret = avcodec_encode_audio2(context, packet, data->aframe[idx],
&got_packet); &got_packet);
#endif #endif
if (ret < 0) { if (ret < 0) {
blog(LOG_WARNING, "encode_audio: Error encoding audio: %s", blog(LOG_WARNING, "encode_audio: Error encoding audio: %s",
av_err2str(ret)); av_err2str(ret));
//FIXME: stop the encode with an error //FIXME: stop the encode with an error
return; goto fail;
} }
if (!got_packet) if (!got_packet)
return; goto fail;
packet.pts = rescale_ts(packet.pts, context, packet->pts = rescale_ts(packet->pts, context,
data->audio_infos[idx].stream->time_base); data->audio_infos[idx].stream->time_base);
packet.dts = rescale_ts(packet.dts, context, packet->dts = rescale_ts(packet->dts, context,
data->audio_infos[idx].stream->time_base); data->audio_infos[idx].stream->time_base);
packet.duration = packet->duration =
(int)av_rescale_q(packet.duration, context->time_base, (int)av_rescale_q(packet->duration, context->time_base,
data->audio_infos[idx].stream->time_base); data->audio_infos[idx].stream->time_base);
packet.stream_index = data->audio_infos[idx].stream->index; packet->stream_index = data->audio_infos[idx].stream->index;
pthread_mutex_lock(&output->write_mutex); pthread_mutex_lock(&output->write_mutex);
da_push_back(output->packets, &packet); da_push_back(output->packets, &packet);
pthread_mutex_unlock(&output->write_mutex); pthread_mutex_unlock(&output->write_mutex);
os_sem_post(output->write_sem); os_sem_post(output->write_sem);
return;
fail:
av_packet_free(&packet);
} }
/* Given a bitmask for the selected tracks and the mix index, /* Given a bitmask for the selected tracks and the mix index,
@ -978,7 +989,7 @@ static uint64_t get_packet_sys_dts(struct ffmpeg_output *output,
static int process_packet(struct ffmpeg_output *output) static int process_packet(struct ffmpeg_output *output)
{ {
AVPacket packet; AVPacket *packet;
bool new_packet = false; bool new_packet = false;
int ret; int ret;
@ -999,16 +1010,16 @@ static int process_packet(struct ffmpeg_output *output)
packet.stream_index, output->packets.num);*/ packet.stream_index, output->packets.num);*/
if (stopping(output)) { if (stopping(output)) {
uint64_t sys_ts = get_packet_sys_dts(output, &packet); uint64_t sys_ts = get_packet_sys_dts(output, packet);
if (sys_ts >= output->stop_ts) if (sys_ts >= output->stop_ts)
return 0; return 0;
} }
output->total_bytes += packet.size; output->total_bytes += packet->size;
ret = av_interleaved_write_frame(output->ff_data.output, &packet); ret = av_interleaved_write_frame(output->ff_data.output, packet);
if (ret < 0) { if (ret < 0) {
av_free_packet(&packet); av_packet_free(&packet);
ffmpeg_log_error(LOG_WARNING, &output->ff_data, ffmpeg_log_error(LOG_WARNING, &output->ff_data,
"process_packet: Error writing packet: %s", "process_packet: Error writing packet: %s",
av_err2str(ret)); av_err2str(ret));
@ -1243,7 +1254,7 @@ static void ffmpeg_deactivate(struct ffmpeg_output *output)
pthread_mutex_lock(&output->write_mutex); pthread_mutex_lock(&output->write_mutex);
for (size_t i = 0; i < output->packets.num; i++) for (size_t i = 0; i < output->packets.num; i++)
av_free_packet(output->packets.array + i); av_packet_free(output->packets.array + i);
da_free(output->packets); da_free(output->packets);
pthread_mutex_unlock(&output->write_mutex); pthread_mutex_unlock(&output->write_mutex);

View File

@ -57,6 +57,8 @@ struct vaapi_encoder {
AVCodec *vaapi; AVCodec *vaapi;
AVCodecContext *context; AVCodecContext *context;
AVPacket *packet;
AVFrame *vframe; AVFrame *vframe;
DARRAY(uint8_t) buffer; DARRAY(uint8_t) buffer;
@ -159,6 +161,8 @@ static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path)
return false; return false;
} }
enc->packet = av_packet_alloc();
enc->initialized = true; enc->initialized = true;
return true; return true;
} }
@ -298,29 +302,33 @@ static bool vaapi_update(void *data, obs_data_t *settings)
return vaapi_init_codec(enc, device); return vaapi_init_codec(enc, device);
} }
static inline void flush_remaining_packets(struct vaapi_encoder *enc)
{
int r_pkt = 1;
while (r_pkt) {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
if (avcodec_receive_packet(enc->context, enc->packet) < 0)
break;
#else
if (avcodec_encode_video2(enc->context, enc->packet, NULL,
&r_pkt) < 0)
break;
#endif
if (r_pkt)
av_packet_unref(enc->packet);
}
}
static void vaapi_destroy(void *data) static void vaapi_destroy(void *data)
{ {
struct vaapi_encoder *enc = data; struct vaapi_encoder *enc = data;
if (enc->initialized) { if (enc->initialized)
AVPacket pkt = {0}; flush_remaining_packets(enc);
int r_pkt = 1;
while (r_pkt) {
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
if (avcodec_receive_packet(enc->context, &pkt) < 0)
break;
#else
if (avcodec_encode_video2(enc->context, &pkt, NULL,
&r_pkt) < 0)
break;
#endif
if (r_pkt)
av_packet_unref(&pkt);
}
}
av_packet_free(&enc->packet);
avcodec_close(enc->context); avcodec_close(enc->context);
av_frame_unref(enc->vframe); av_frame_unref(enc->vframe);
av_frame_free(&enc->vframe); av_frame_free(&enc->vframe);
@ -405,7 +413,6 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
{ {
struct vaapi_encoder *enc = data; struct vaapi_encoder *enc = data;
AVFrame *hwframe = NULL; AVFrame *hwframe = NULL;
AVPacket av_pkt;
int got_packet; int got_packet;
int ret; int ret;
@ -443,19 +450,17 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
goto fail; goto fail;
} }
av_init_packet(&av_pkt);
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101) #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 40, 101)
ret = avcodec_send_frame(enc->context, hwframe); ret = avcodec_send_frame(enc->context, hwframe);
if (ret == 0) if (ret == 0)
ret = avcodec_receive_packet(enc->context, &av_pkt); ret = avcodec_receive_packet(enc->context, enc->packet);
got_packet = (ret == 0); got_packet = (ret == 0);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
ret = 0; ret = 0;
#else #else
ret = avcodec_encode_video2(enc->context, &av_pkt, hwframe, ret = avcodec_encode_video2(enc->context, enc->packet, hwframe,
&got_packet); &got_packet);
#endif #endif
if (ret < 0) { if (ret < 0) {
@ -463,25 +468,27 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
goto fail; goto fail;
} }
if (got_packet && av_pkt.size) { if (got_packet && enc->packet->size) {
if (enc->first_packet) { if (enc->first_packet) {
uint8_t *new_packet; uint8_t *new_packet;
size_t size; size_t size;
enc->first_packet = false; enc->first_packet = false;
obs_extract_avc_headers(av_pkt.data, av_pkt.size, obs_extract_avc_headers(enc->packet->data,
&new_packet, &size, enc->packet->size, &new_packet,
&enc->header, &enc->header_size, &size, &enc->header,
&enc->sei, &enc->sei_size); &enc->header_size, &enc->sei,
&enc->sei_size);
da_copy_array(enc->buffer, new_packet, size); da_copy_array(enc->buffer, new_packet, size);
bfree(new_packet); bfree(new_packet);
} else { } else {
da_copy_array(enc->buffer, av_pkt.data, av_pkt.size); da_copy_array(enc->buffer, enc->packet->data,
enc->packet->size);
} }
packet->pts = av_pkt.pts; packet->pts = enc->packet->pts;
packet->dts = av_pkt.dts; packet->dts = enc->packet->dts;
packet->data = enc->buffer.array; packet->data = enc->buffer.array;
packet->size = enc->buffer.num; packet->size = enc->buffer.num;
packet->type = OBS_ENCODER_VIDEO; packet->type = OBS_ENCODER_VIDEO;
@ -491,7 +498,7 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
*received_packet = false; *received_packet = false;
} }
av_packet_unref(&av_pkt); av_packet_unref(enc->packet);
av_frame_free(&hwframe); av_frame_free(&hwframe);
return true; return true;

View File

@ -225,7 +225,6 @@ bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,
size_t size, struct obs_source_audio *audio, size_t size, struct obs_source_audio *audio,
bool *got_output) bool *got_output)
{ {
AVPacket packet = {0};
int got_frame = false; int got_frame = false;
int ret = 0; int ret = 0;
@ -233,18 +232,21 @@ bool ffmpeg_decode_audio(struct ffmpeg_decode *decode, uint8_t *data,
copy_data(decode, data, size); copy_data(decode, data, size);
av_init_packet(&packet);
packet.data = decode->packet_buffer;
packet.size = (int)size;
if (!decode->frame) { if (!decode->frame) {
decode->frame = av_frame_alloc(); decode->frame = av_frame_alloc();
if (!decode->frame) if (!decode->frame)
return false; return false;
} }
if (data && size) if (data && size) {
ret = avcodec_send_packet(decode->decoder, &packet); AVPacket *packet = av_packet_alloc();
packet->data = decode->packet_buffer;
packet->size = (int)size;
ret = avcodec_send_packet(decode->decoder, packet);
av_packet_free(&packet);
}
if (ret == 0) if (ret == 0)
ret = avcodec_receive_frame(decode->decoder, decode->frame); ret = avcodec_receive_frame(decode->decoder, decode->frame);
@ -297,7 +299,6 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
enum video_range_type range, enum video_range_type range,
struct obs_source_frame2 *frame, bool *got_output) struct obs_source_frame2 *frame, bool *got_output)
{ {
AVPacket packet = {0};
int got_frame = false; int got_frame = false;
AVFrame *out_frame; AVFrame *out_frame;
int ret; int ret;
@ -306,15 +307,6 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
copy_data(decode, data, size); copy_data(decode, data, size);
av_init_packet(&packet);
packet.data = decode->packet_buffer;
packet.size = (int)size;
packet.pts = *ts;
if (decode->codec->id == AV_CODEC_ID_H264 &&
obs_avc_keyframe(data, size))
packet.flags |= AV_PKT_FLAG_KEY;
if (!decode->frame) { if (!decode->frame) {
decode->frame = av_frame_alloc(); decode->frame = av_frame_alloc();
if (!decode->frame) if (!decode->frame)
@ -329,11 +321,22 @@ bool ffmpeg_decode_video(struct ffmpeg_decode *decode, uint8_t *data,
out_frame = decode->hw ? decode->hw_frame : decode->frame; out_frame = decode->hw ? decode->hw_frame : decode->frame;
ret = avcodec_send_packet(decode->decoder, &packet); AVPacket *packet = av_packet_alloc();
packet->data = decode->packet_buffer;
packet->size = (int)size;
packet->pts = *ts;
if (decode->codec->id == AV_CODEC_ID_H264 &&
obs_avc_keyframe(data, size))
packet->flags |= AV_PKT_FLAG_KEY;
ret = avcodec_send_packet(decode->decoder, packet);
if (ret == 0) { if (ret == 0) {
ret = avcodec_receive_frame(decode->decoder, out_frame); ret = avcodec_receive_frame(decode->decoder, out_frame);
} }
av_packet_free(&packet);
got_frame = (ret == 0); got_frame = (ret == 0);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))