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:
parent
85addc3dac
commit
ba68eda590
@ -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",
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user