Skip to content
Snippets Groups Projects
Commit 43f22d20 authored by Philippe Gorley's avatar Philippe Gorley Committed by Sébastien Blin
Browse files

encoder: merge common encoding code


Refactors out the common code from video and audio encoding/flushing
into a single method. This reuses code instead of duplicating it.

The method is public in the hopes of being able to reuse MediaEncoder
elsewhere in the codebase.

Allow caller to specify the stream index for the future case that the
AVFormatContext contains multiple streams (recording video and audio).

Change-Id: Ieae52bc453ef66d141a40819ca10fedbd38d9a86
Reviewed-by: default avatarSebastien Blin <sebastien.blin@savoirfairelinux.com>
parent a52424ae
Branches
Tags
No related merge requests found
......@@ -300,42 +300,7 @@ MediaEncoder::encode(VideoFrame& input, bool is_keyframe,
frame->key_frame = 0;
}
AVPacket pkt;
memset(&pkt, 0, sizeof(pkt));
av_init_packet(&pkt);
int ret = 0;
ret = avcodec_send_frame(encoderCtx_, frame);
if (ret < 0)
return -1;
while (1) {
ret = avcodec_receive_packet(encoderCtx_, &pkt);
if (ret == AVERROR(EAGAIN))
break;
if (ret < 0)
return -1;
if (pkt.size) {
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
stream_->time_base);
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
stream_->time_base);
pkt.stream_index = stream_->index;
// write the compressed frame
ret = av_write_frame(outputCtx_, &pkt);
if (ret < 0) {
RING_ERR("av_write_frame failed: %s", libav_utils::getError(ret).c_str());
} else
break;
}
}
av_packet_unref(&pkt);
int ret = encode(frame, stream_->index);
return ret;
}
......@@ -394,8 +359,8 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
reinterpret_cast<const uint8_t *>(offset_ptr),
buffer_size, 0);
if (err < 0) {
RING_ERR("Couldn't fill audio frame: %s: %d %d", libav_utils::getError(err).c_str(),
frame->nb_samples, buffer_size);
RING_ERR() << "Failed to fill audio frame of size" << buffer_size << " with "
<< frame->nb_samples << " samples: " << libav_utils::getError(err);
av_frame_free(&frame);
return -1;
}
......@@ -403,66 +368,35 @@ int MediaEncoder::encode_audio(const AudioBuffer &buffer)
nb_frames -= frame->nb_samples;
offset_ptr += frame->nb_samples * buffer.channels();
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
int ret = 0;
ret = avcodec_send_frame(encoderCtx_, frame);
if (ret < 0)
return -1;
while (1) {
ret = avcodec_receive_packet(encoderCtx_, &pkt);
if (ret == AVERROR(EAGAIN))
break;
if (ret < 0)
return -1;
if (pkt.size) {
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(pkt.pts, encoderCtx_->time_base,
stream_->time_base);
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
stream_->time_base);
pkt.stream_index = stream_->index;
// write the compressed frame
ret = av_write_frame(outputCtx_, &pkt);
if (ret < 0) {
RING_ERR("av_write_frame failed: %s", libav_utils::getError(ret).c_str());
} else
break;
}
}
av_packet_unref(&pkt);
encode(frame, stream_->index);
av_frame_free(&frame);
}
return 0;
}
int MediaEncoder::flush()
int
MediaEncoder::encode(AVFrame* frame, int streamIdx)
{
int ret = 0;
AVPacket pkt;
memset(&pkt, 0, sizeof(pkt));
av_init_packet(&pkt);
pkt.data = NULL; // packet data will be allocated by the encoder
pkt.size = 0;
pkt.stream_index = streamIdx;
int ret = 0;
ret = avcodec_send_frame(encoderCtx_, nullptr);
ret = avcodec_send_frame(encoderCtx_, frame);
if (ret < 0)
return -1;
while (1) {
while (ret >= 0) {
ret = avcodec_receive_packet(encoderCtx_, &pkt);
if (ret == AVERROR(EAGAIN))
break;
if (ret < 0)
return -1;
if (ret < 0) {
RING_ERR() << "Failed to encode frame: " << libav_utils::getError(ret);
return ret;
}
if (pkt.size) {
if (pkt.pts != AV_NOPTS_VALUE)
......@@ -472,19 +406,24 @@ int MediaEncoder::flush()
pkt.dts = av_rescale_q(pkt.dts, encoderCtx_->time_base,
stream_->time_base);
pkt.stream_index = stream_->index;
// write the compressed frame
ret = av_write_frame(outputCtx_, &pkt);
if (ret < 0) {
RING_ERR("av_write_frame failed: %s", libav_utils::getError(ret).c_str());
RING_ERR() << "av_write_frame failed: " << libav_utils::getError(ret);
} else
break;
}
}
av_packet_unref(&pkt);
return 0;
}
return ret;
int
MediaEncoder::flush()
{
return encode(nullptr, stream_->index);
}
std::string
......
......@@ -72,6 +72,10 @@ public:
#endif // RING_VIDEO
int encode_audio(const AudioBuffer &input);
// frame should be ready to be sent to the encoder at this point
int encode(AVFrame* frame, int streamIdx);
int flush();
std::string print_sdp();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment