2017-12-12 22:12:07 +08:00
|
|
|
#include "decoder.h"
|
|
|
|
|
2021-09-21 00:27:37 +08:00
|
|
|
#include <libavcodec/avcodec.h>
|
2017-12-12 22:12:07 +08:00
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
|
|
|
|
#include "events.h"
|
2019-03-02 22:16:55 +08:00
|
|
|
#include "video_buffer.h"
|
2021-04-11 21:01:05 +08:00
|
|
|
#include "trait/frame_sink.h"
|
2019-11-24 18:53:00 +08:00
|
|
|
#include "util/log.h"
|
2017-12-12 22:12:07 +08:00
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
/** Downcast packet_sink to decoder */
|
2022-02-03 02:27:41 +08:00
|
|
|
#define DOWNCAST(SINK) container_of(SINK, struct sc_decoder, packet_sink)
|
2021-04-11 21:01:05 +08:00
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
static void
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_close_first_sinks(struct sc_decoder *decoder, unsigned count) {
|
2021-04-11 21:01:05 +08:00
|
|
|
while (count) {
|
|
|
|
struct sc_frame_sink *sink = decoder->sinks[--count];
|
|
|
|
sink->ops->close(sink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_close_sinks(struct sc_decoder *decoder) {
|
|
|
|
sc_decoder_close_first_sinks(decoder, decoder->sink_count);
|
2021-04-11 21:01:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_open_sinks(struct sc_decoder *decoder) {
|
2021-04-11 21:01:05 +08:00
|
|
|
for (unsigned i = 0; i < decoder->sink_count; ++i) {
|
|
|
|
struct sc_frame_sink *sink = decoder->sinks[i];
|
|
|
|
if (!sink->ops->open(sink)) {
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_close_first_sinks(decoder, i);
|
2021-04-11 21:01:05 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_open(struct sc_decoder *decoder, const AVCodec *codec) {
|
2019-03-02 23:43:43 +08:00
|
|
|
decoder->codec_ctx = avcodec_alloc_context3(codec);
|
|
|
|
if (!decoder->codec_ctx) {
|
2021-11-25 05:06:11 +08:00
|
|
|
LOG_OOM();
|
2019-03-03 06:52:22 +08:00
|
|
|
return false;
|
2017-12-12 22:12:07 +08:00
|
|
|
}
|
|
|
|
|
2021-12-07 20:59:20 +08:00
|
|
|
decoder->codec_ctx->flags |= AV_CODEC_FLAG_LOW_DELAY;
|
|
|
|
|
2019-03-02 23:43:43 +08:00
|
|
|
if (avcodec_open2(decoder->codec_ctx, codec, NULL) < 0) {
|
2023-02-25 04:22:35 +08:00
|
|
|
LOGE("Decoder '%s': could not open codec", decoder->name);
|
2019-03-02 23:43:43 +08:00
|
|
|
avcodec_free_context(&decoder->codec_ctx);
|
2019-03-03 06:52:22 +08:00
|
|
|
return false;
|
2017-12-12 22:12:07 +08:00
|
|
|
}
|
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
decoder->frame = av_frame_alloc();
|
|
|
|
if (!decoder->frame) {
|
2021-11-25 05:06:11 +08:00
|
|
|
LOG_OOM();
|
2021-04-11 21:01:05 +08:00
|
|
|
avcodec_close(decoder->codec_ctx);
|
|
|
|
avcodec_free_context(&decoder->codec_ctx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-02-03 02:27:41 +08:00
|
|
|
if (!sc_decoder_open_sinks(decoder)) {
|
2021-04-11 21:01:05 +08:00
|
|
|
av_frame_free(&decoder->frame);
|
|
|
|
avcodec_close(decoder->codec_ctx);
|
|
|
|
avcodec_free_context(&decoder->codec_ctx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-03 06:52:22 +08:00
|
|
|
return true;
|
2019-03-02 23:43:43 +08:00
|
|
|
}
|
2018-10-11 13:12:36 +08:00
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
static void
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_close(struct sc_decoder *decoder) {
|
|
|
|
sc_decoder_close_sinks(decoder);
|
2021-04-11 21:01:05 +08:00
|
|
|
av_frame_free(&decoder->frame);
|
2019-03-02 23:43:43 +08:00
|
|
|
avcodec_close(decoder->codec_ctx);
|
|
|
|
avcodec_free_context(&decoder->codec_ctx);
|
|
|
|
}
|
2017-12-12 22:12:07 +08:00
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
static bool
|
2022-02-03 02:27:41 +08:00
|
|
|
push_frame_to_sinks(struct sc_decoder *decoder, const AVFrame *frame) {
|
2021-04-11 21:01:05 +08:00
|
|
|
for (unsigned i = 0; i < decoder->sink_count; ++i) {
|
|
|
|
struct sc_frame_sink *sink = decoder->sinks[i];
|
|
|
|
if (!sink->ops->push(sink, frame)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
static bool
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_push(struct sc_decoder *decoder, const AVPacket *packet) {
|
2021-04-11 21:01:05 +08:00
|
|
|
bool is_config = packet->pts == AV_NOPTS_VALUE;
|
|
|
|
if (is_config) {
|
|
|
|
// nothing to do
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-18 23:13:58 +08:00
|
|
|
int ret = avcodec_send_packet(decoder->codec_ctx, packet);
|
|
|
|
if (ret < 0 && ret != AVERROR(EAGAIN)) {
|
2023-02-25 04:22:35 +08:00
|
|
|
LOGE("Decoder '%s': could not send video packet: %d",
|
|
|
|
decoder->name, ret);
|
2019-03-03 06:52:22 +08:00
|
|
|
return false;
|
2017-12-12 22:12:07 +08:00
|
|
|
}
|
2021-04-11 21:01:05 +08:00
|
|
|
ret = avcodec_receive_frame(decoder->codec_ctx, decoder->frame);
|
2019-03-02 23:43:43 +08:00
|
|
|
if (!ret) {
|
|
|
|
// a frame was received
|
2021-04-11 21:01:05 +08:00
|
|
|
bool ok = push_frame_to_sinks(decoder, decoder->frame);
|
2021-04-11 21:01:05 +08:00
|
|
|
// A frame lost should not make the whole pipeline fail. The error, if
|
|
|
|
// any, is already logged.
|
|
|
|
(void) ok;
|
2021-04-27 00:05:43 +08:00
|
|
|
|
|
|
|
av_frame_unref(decoder->frame);
|
2019-03-02 23:43:43 +08:00
|
|
|
} else if (ret != AVERROR(EAGAIN)) {
|
2023-02-25 04:22:35 +08:00
|
|
|
LOGE("Decoder '%s', could not receive video frame: %d",
|
|
|
|
decoder->name, ret);
|
2019-03-03 06:52:22 +08:00
|
|
|
return false;
|
2018-10-11 13:12:36 +08:00
|
|
|
}
|
2019-03-03 06:52:22 +08:00
|
|
|
return true;
|
2017-12-12 22:12:07 +08:00
|
|
|
}
|
2021-04-11 21:01:05 +08:00
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
static bool
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_packet_sink_open(struct sc_packet_sink *sink, const AVCodec *codec) {
|
|
|
|
struct sc_decoder *decoder = DOWNCAST(sink);
|
|
|
|
return sc_decoder_open(decoder, codec);
|
2021-04-11 21:01:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_packet_sink_close(struct sc_packet_sink *sink) {
|
|
|
|
struct sc_decoder *decoder = DOWNCAST(sink);
|
|
|
|
sc_decoder_close(decoder);
|
2021-04-11 21:01:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_packet_sink_push(struct sc_packet_sink *sink,
|
|
|
|
const AVPacket *packet) {
|
|
|
|
struct sc_decoder *decoder = DOWNCAST(sink);
|
|
|
|
return sc_decoder_push(decoder, packet);
|
2021-04-11 21:01:05 +08:00
|
|
|
}
|
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
void
|
2023-02-25 04:22:35 +08:00
|
|
|
sc_decoder_init(struct sc_decoder *decoder, const char *name) {
|
|
|
|
decoder->name = name; // statically allocated
|
2021-05-29 03:23:10 +08:00
|
|
|
decoder->sink_count = 0;
|
|
|
|
|
2021-04-11 21:01:05 +08:00
|
|
|
static const struct sc_packet_sink_ops ops = {
|
2022-02-03 02:27:41 +08:00
|
|
|
.open = sc_decoder_packet_sink_open,
|
|
|
|
.close = sc_decoder_packet_sink_close,
|
|
|
|
.push = sc_decoder_packet_sink_push,
|
2021-04-11 21:01:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
decoder->packet_sink.ops = &ops;
|
2021-04-11 21:01:05 +08:00
|
|
|
}
|
2021-04-11 21:01:05 +08:00
|
|
|
|
|
|
|
void
|
2022-02-03 02:27:41 +08:00
|
|
|
sc_decoder_add_sink(struct sc_decoder *decoder, struct sc_frame_sink *sink) {
|
|
|
|
assert(decoder->sink_count < SC_DECODER_MAX_SINKS);
|
2021-04-11 21:01:05 +08:00
|
|
|
assert(sink);
|
|
|
|
assert(sink->ops);
|
|
|
|
decoder->sinks[decoder->sink_count++] = sink;
|
|
|
|
}
|