-void
-FFmpegEncoder::video (shared_ptr<PlayerVideo> video, DCPTime time)
-{
- shared_ptr<Image> image = video->image (
- bind (&Log::dcp_log, _film->log().get(), _1, _2),
- bind (&force_pixel_format, _1, _pixel_format),
- true,
- false
- );
-
- AVFrame* frame = av_frame_alloc ();
- DCPOMATIC_ASSERT (frame);
-
- for (int i = 0; i < 3; ++i) {
- size_t const size = image->stride()[i] * image->sample_size(i).height;
- AVBufferRef* buffer = av_buffer_alloc (size);
- DCPOMATIC_ASSERT (buffer);
- /* XXX: inefficient */
- memcpy (buffer->data, image->data()[i], size);
- frame->buf[i] = av_buffer_ref (buffer);
- frame->data[i] = buffer->data;
- frame->linesize[i] = image->stride()[i];
- av_buffer_unref (&buffer);
- }
-
- frame->width = image->size().width;
- frame->height = image->size().height;
- frame->format = _pixel_format;
- frame->pts = time.seconds() / av_q2d (_video_stream->time_base);
-
- AVPacket packet;
- av_init_packet (&packet);
- packet.data = 0;
- packet.size = 0;
-
- int got_packet;
- if (avcodec_encode_video2 (_video_codec_context, &packet, frame, &got_packet) < 0) {
- throw EncodeError ("FFmpeg video encode failed");
- }
-
- if (got_packet && packet.size) {
- packet.stream_index = _video_stream_index;
- av_interleaved_write_frame (_format_context, &packet);
- av_packet_unref (&packet);
- }
-
- av_frame_free (&frame);
-
- _history.event ();
-
- {
- boost::mutex::scoped_lock lm (_mutex);
- _last_time = time;
- }
-
- shared_ptr<Job> job = _job.lock ();
- if (job) {
- job->set_progress (float(time.get()) / _film->length().get());
- }
-}
-
-/** Called when the player gives us some audio */
-void
-FFmpegEncoder::audio (shared_ptr<AudioBuffers> audio, DCPTime)
-{
- _pending_audio->append (remap (audio, _audio_mapping.output_channels(), _audio_mapping));
-
- int frame_size = _audio_codec_context->frame_size;
- if (frame_size == 0) {
- /* codec has AV_CODEC_CAP_VARIABLE_FRAME_SIZE */
- frame_size = 2000;
- }
-
- while (_pending_audio->frames() >= frame_size) {
- audio_frame (frame_size);
- }
-}
-
-void
-FFmpegEncoder::audio_frame (int size)
-{
- DCPOMATIC_ASSERT (size);
-
- AVFrame* frame = av_frame_alloc ();
- DCPOMATIC_ASSERT (frame);
-
- int const channels = _pending_audio->channels();
- DCPOMATIC_ASSERT (channels);
-
- int const buffer_size = av_samples_get_buffer_size (0, channels, size, _audio_codec_context->sample_fmt, 0);
- DCPOMATIC_ASSERT (buffer_size >= 0);
-
- void* samples = av_malloc (buffer_size);
- DCPOMATIC_ASSERT (samples);
-
- frame->nb_samples = size;
- int r = avcodec_fill_audio_frame (frame, channels, _audio_codec_context->sample_fmt, (const uint8_t *) samples, buffer_size, 0);
- DCPOMATIC_ASSERT (r >= 0);
-
- float** p = _pending_audio->data ();
- switch (_audio_codec_context->sample_fmt) {
- case AV_SAMPLE_FMT_S16:
- {
- int16_t* q = reinterpret_cast<int16_t*> (samples);
- for (int i = 0; i < size; ++i) {
- for (int j = 0; j < channels; ++j) {
- *q++ = p[j][i] * 32767;