|
|
|
|
@ -422,8 +422,10 @@ static const char *avc_decoder_init(decoder_t *dec, const str *fmtp) {
|
|
|
|
|
dec->def->set_dec_options(dec, fmtp);
|
|
|
|
|
|
|
|
|
|
int i = avcodec_open2(dec->u.avc.avcctx, codec, NULL);
|
|
|
|
|
if (i)
|
|
|
|
|
if (i) {
|
|
|
|
|
ilog(LOG_ERR, "Error returned from libav: %s", av_error(i));
|
|
|
|
|
return "failed to open codec context";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const enum AVSampleFormat *sfmt = codec->sample_fmts; sfmt && *sfmt != -1; sfmt++)
|
|
|
|
|
dbg("supported sample format for input codec %s: %s",
|
|
|
|
|
@ -506,6 +508,7 @@ void decoder_close(decoder_t *dec) {
|
|
|
|
|
|
|
|
|
|
static int avc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
|
|
|
|
|
const char *err;
|
|
|
|
|
int av_ret = 0;
|
|
|
|
|
|
|
|
|
|
dec->u.avc.avpkt.data = (unsigned char *) data->s;
|
|
|
|
|
dec->u.avc.avpkt.size = data->len;
|
|
|
|
|
@ -525,32 +528,32 @@ static int avc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
|
|
|
|
|
|
|
|
|
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 36, 0)
|
|
|
|
|
if (dec->u.avc.avpkt.size) {
|
|
|
|
|
int ret = avcodec_send_packet(dec->u.avc.avcctx, &dec->u.avc.avpkt);
|
|
|
|
|
dbg("send packet ret %i", ret);
|
|
|
|
|
av_ret = avcodec_send_packet(dec->u.avc.avcctx, &dec->u.avc.avpkt);
|
|
|
|
|
dbg("send packet ret %i", av_ret);
|
|
|
|
|
err = "failed to send packet to avcodec";
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
if (av_ret == 0) {
|
|
|
|
|
// consumed the packet
|
|
|
|
|
dec->u.avc.avpkt.size = 0;
|
|
|
|
|
keep_going = 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (ret == AVERROR(EAGAIN))
|
|
|
|
|
if (av_ret == AVERROR(EAGAIN))
|
|
|
|
|
; // try again after reading output
|
|
|
|
|
else
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ret = avcodec_receive_frame(dec->u.avc.avcctx, frame);
|
|
|
|
|
dbg("receive frame ret %i", ret);
|
|
|
|
|
av_ret = avcodec_receive_frame(dec->u.avc.avcctx, frame);
|
|
|
|
|
dbg("receive frame ret %i", av_ret);
|
|
|
|
|
err = "failed to receive frame from avcodec";
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
if (av_ret == 0) {
|
|
|
|
|
// got a frame
|
|
|
|
|
keep_going = 1;
|
|
|
|
|
got_frame = 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (ret == AVERROR(EAGAIN))
|
|
|
|
|
if (av_ret == AVERROR(EAGAIN))
|
|
|
|
|
; // maybe needs more input now
|
|
|
|
|
else
|
|
|
|
|
goto err;
|
|
|
|
|
@ -560,18 +563,18 @@ static int avc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
|
|
|
|
|
if (dec->u.avc.avpkt.size == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
int ret = avcodec_decode_audio4(dec->u.avc.avcctx, frame, &got_frame, &dec->u.avc.avpkt);
|
|
|
|
|
dbg("decode frame ret %i, got frame %i", ret, got_frame);
|
|
|
|
|
av_ret = avcodec_decode_audio4(dec->u.avc.avcctx, frame, &got_frame, &dec->u.avc.avpkt);
|
|
|
|
|
dbg("decode frame ret %i, got frame %i", av_ret, got_frame);
|
|
|
|
|
err = "failed to decode audio packet";
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
if (av_ret < 0)
|
|
|
|
|
goto err;
|
|
|
|
|
if (ret > 0) {
|
|
|
|
|
if (av_ret > 0) {
|
|
|
|
|
// consumed some input
|
|
|
|
|
err = "invalid return value";
|
|
|
|
|
if (ret > dec->u.avc.avpkt.size)
|
|
|
|
|
if (av_ret > dec->u.avc.avpkt.size)
|
|
|
|
|
goto err;
|
|
|
|
|
dec->u.avc.avpkt.size -= ret;
|
|
|
|
|
dec->u.avc.avpkt.data += ret;
|
|
|
|
|
dec->u.avc.avpkt.size -= av_ret;
|
|
|
|
|
dec->u.avc.avpkt.data += av_ret;
|
|
|
|
|
keep_going = 1;
|
|
|
|
|
}
|
|
|
|
|
if (got_frame)
|
|
|
|
|
@ -599,6 +602,8 @@ static int avc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
ilog(LOG_ERR | LOG_FLAG_LIMIT, "Error decoding media packet: %s", err);
|
|
|
|
|
if (av_ret)
|
|
|
|
|
ilog(LOG_ERR, "Error returned from libav: %s", av_error(av_ret));
|
|
|
|
|
av_frame_free(&frame);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
@ -985,8 +990,10 @@ static const char *avc_encoder_init(encoder_t *enc, const str *fmtp) {
|
|
|
|
|
enc->def->set_enc_options(enc, fmtp);
|
|
|
|
|
|
|
|
|
|
int i = avcodec_open2(enc->u.avc.avcctx, enc->u.avc.codec, NULL);
|
|
|
|
|
if (i)
|
|
|
|
|
if (i) {
|
|
|
|
|
ilog(LOG_ERR, "Error returned from libav: %s", av_error(i));
|
|
|
|
|
return "failed to open output context";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
@ -1081,50 +1088,51 @@ void encoder_free(encoder_t *enc) {
|
|
|
|
|
static int avc_encoder_input(encoder_t *enc, AVFrame **frame) {
|
|
|
|
|
int keep_going = 0;
|
|
|
|
|
int got_packet = 0;
|
|
|
|
|
int av_ret = 0;
|
|
|
|
|
|
|
|
|
|
if (!enc->u.avc.avcctx)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 36, 0)
|
|
|
|
|
if (*frame) {
|
|
|
|
|
int ret = avcodec_send_frame(enc->u.avc.avcctx, *frame);
|
|
|
|
|
dbg("send frame ret %i", ret);
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
av_ret = avcodec_send_frame(enc->u.avc.avcctx, *frame);
|
|
|
|
|
dbg("send frame ret %i", av_ret);
|
|
|
|
|
if (av_ret == 0) {
|
|
|
|
|
// consumed
|
|
|
|
|
*frame = NULL;
|
|
|
|
|
keep_going = 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (ret == AVERROR(EAGAIN))
|
|
|
|
|
if (av_ret == AVERROR(EAGAIN))
|
|
|
|
|
; // check output and maybe try again
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ret = avcodec_receive_packet(enc->u.avc.avcctx, &enc->avpkt);
|
|
|
|
|
dbg("receive packet ret %i", ret);
|
|
|
|
|
if (ret == 0) {
|
|
|
|
|
av_ret = avcodec_receive_packet(enc->u.avc.avcctx, &enc->avpkt);
|
|
|
|
|
dbg("receive packet ret %i", av_ret);
|
|
|
|
|
if (av_ret == 0) {
|
|
|
|
|
// got some data
|
|
|
|
|
keep_going = 1;
|
|
|
|
|
got_packet = 1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (ret == AVERROR(EAGAIN))
|
|
|
|
|
if (av_ret == AVERROR(EAGAIN))
|
|
|
|
|
; // try again if there's still more input
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if (!*frame)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
int ret = avcodec_encode_audio2(enc->u.avc.avcctx, &enc->avpkt, *frame, &got_packet);
|
|
|
|
|
dbg("encode frame ret %i, got packet %i", ret, got_packet);
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
av_ret = avcodec_encode_audio2(enc->u.avc.avcctx, &enc->avpkt, *frame, &got_packet);
|
|
|
|
|
dbg("encode frame ret %i, got packet %i", av_ret, got_packet);
|
|
|
|
|
if (av_ret == 0)
|
|
|
|
|
*frame = NULL; // consumed
|
|
|
|
|
else
|
|
|
|
|
return -1; // error
|
|
|
|
|
goto err;
|
|
|
|
|
if (got_packet)
|
|
|
|
|
keep_going = 1;
|
|
|
|
|
#endif
|
|
|
|
|
@ -1145,6 +1153,11 @@ static int avc_encoder_input(encoder_t *enc, AVFrame **frame) {
|
|
|
|
|
enc->avpkt.pts = enc->avpkt.dts;
|
|
|
|
|
|
|
|
|
|
return keep_going;
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
if (av_ret)
|
|
|
|
|
ilog(LOG_ERR, "Error returned from libav: %s", av_error(av_ret));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int encoder_input_data(encoder_t *enc, AVFrame *frame,
|
|
|
|
|
@ -1299,7 +1312,8 @@ static void opus_set_enc_options(encoder_t *enc, const str *fmtp) {
|
|
|
|
|
int ret;
|
|
|
|
|
if (enc->ptime)
|
|
|
|
|
if ((ret = av_opt_set_int(enc->u.avc.avcctx, "frame_duration", enc->ptime, 0)))
|
|
|
|
|
ilog(LOG_WARN, "Failed to set Opus frame_duration option (error code %i)", ret);
|
|
|
|
|
ilog(LOG_WARN, "Failed to set Opus frame_duration option to %i: %s",
|
|
|
|
|
enc->ptime, av_error(ret));
|
|
|
|
|
// XXX additional opus options
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|