-void QuickSyncEncoderImpl::encode_audio(
- const vector<float> &audio,
- vector<float> *audio_queue,
- int64_t audio_pts,
- AVCodecContext *ctx,
- AVAudioResampleContext *resampler,
- const vector<Mux *> &muxes)
-{
- if (ctx->frame_size == 0) {
- // No queueing needed.
- assert(audio_queue->empty());
- assert(audio.size() % 2 == 0);
- encode_audio_one_frame(&audio[0], audio.size() / 2, audio_pts, ctx, resampler, muxes);
- return;
- }
-
- int64_t sample_offset = audio_queue->size();
-
- audio_queue->insert(audio_queue->end(), audio.begin(), audio.end());
- size_t sample_num;
- for (sample_num = 0;
- sample_num + ctx->frame_size * 2 <= audio_queue->size();
- sample_num += ctx->frame_size * 2) {
- int64_t adjusted_audio_pts = audio_pts + (int64_t(sample_num) - sample_offset) * TIMEBASE / (OUTPUT_FREQUENCY * 2);
- encode_audio_one_frame(&(*audio_queue)[sample_num],
- ctx->frame_size,
- adjusted_audio_pts,
- ctx,
- resampler,
- muxes);
- }
- audio_queue->erase(audio_queue->begin(), audio_queue->begin() + sample_num);
-}
-
-void QuickSyncEncoderImpl::encode_audio_one_frame(
- const float *audio,
- size_t num_samples,
- int64_t audio_pts,
- AVCodecContext *ctx,
- AVAudioResampleContext *resampler,
- const vector<Mux *> &muxes)
-{
- audio_frame->pts = audio_pts + global_delay();
- audio_frame->nb_samples = num_samples;
- audio_frame->channel_layout = AV_CH_LAYOUT_STEREO;
- audio_frame->format = ctx->sample_fmt;
- audio_frame->sample_rate = OUTPUT_FREQUENCY;
-
- if (av_samples_alloc(audio_frame->data, nullptr, 2, num_samples, ctx->sample_fmt, 0) < 0) {
- fprintf(stderr, "Could not allocate %ld samples.\n", num_samples);
- exit(1);
- }
-
- if (avresample_convert(resampler, audio_frame->data, 0, num_samples,
- (uint8_t **)&audio, 0, num_samples) < 0) {
- fprintf(stderr, "Audio conversion failed.\n");
- exit(1);
- }
-
- AVPacket pkt;
- av_init_packet(&pkt);
- pkt.data = nullptr;
- pkt.size = 0;
- int got_output = 0;
- avcodec_encode_audio2(ctx, &pkt, audio_frame, &got_output);
- if (got_output) {
- pkt.stream_index = 1;
- pkt.flags = 0;
- for (Mux *mux : muxes) {
- mux->add_packet(pkt, pkt.pts, pkt.dts);
- }
- }
-
- av_freep(&audio_frame->data[0]);
-
- av_frame_unref(audio_frame);
- av_free_packet(&pkt);
-}
-
-void QuickSyncEncoderImpl::encode_last_audio(
- vector<float> *audio_queue,
- int64_t audio_pts,
- AVCodecContext *ctx,
- AVAudioResampleContext *resampler,
- const vector<Mux *> &muxes)
-{
- if (!audio_queue->empty()) {
- // Last frame can be whatever size we want.
- assert(audio_queue->size() % 2 == 0);
- encode_audio_one_frame(&(*audio_queue)[0], audio_queue->size() / 2, audio_pts, ctx, resampler, muxes);
- audio_queue->clear();
- }
-
- if (ctx->codec->capabilities & AV_CODEC_CAP_DELAY) {
- // Collect any delayed frames.
- for ( ;; ) {
- int got_output = 0;
- AVPacket pkt;
- av_init_packet(&pkt);
- pkt.data = nullptr;
- pkt.size = 0;
- avcodec_encode_audio2(ctx, &pkt, nullptr, &got_output);
- if (!got_output) break;
-
- pkt.stream_index = 1;
- pkt.flags = 0;
- for (Mux *mux : muxes) {
- mux->add_packet(pkt, pkt.pts, pkt.dts);
- }
- av_free_packet(&pkt);
- }
- }
-}