Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Mueller <nexyon@gmail.com>2013-04-01 19:31:27 +0400
committerJoerg Mueller <nexyon@gmail.com>2013-04-01 19:31:27 +0400
commit8588fec935c47529d9c1816f19e94ff0d20ed1a9 (patch)
tree0b69097d38f21e3295f8121f86ad50d4f422527e /source/blender/blenkernel/intern/writeffmpeg.c
parentc35dec60b5e54e4b1b7c6fbb0f17a3b1f0f86012 (diff)
FFMPEG: adding support for ffmpeg planar formats also to writeffmpeg.c.
Diffstat (limited to 'source/blender/blenkernel/intern/writeffmpeg.c')
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c124
1 files changed, 82 insertions, 42 deletions
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index a88a9e4954b..f671a3cfc05 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -88,10 +88,11 @@ static uint8_t *video_buffer = 0;
static int video_buffersize = 0;
static uint8_t *audio_input_buffer = 0;
+static uint8_t *audio_deinterleave_buffer = 0;
static int audio_input_samples = 0;
-static uint8_t *audio_output_buffer = 0;
-static int audio_outbuf_size = 0;
static double audio_time = 0.0f;
+static bool audio_deinterleave = false;
+static int audio_sample_size = 0;
#ifdef WITH_AUDASPACE
static AUD_Device *audio_mixdown_device = 0;
@@ -122,37 +123,67 @@ static int write_audio_frame(void)
{
AVCodecContext *c = NULL;
AVPacket pkt;
+ AVFrame* frame;
+ int got_output = 0;
c = audio_stream->codec;
av_init_packet(&pkt);
pkt.size = 0;
+ pkt.data = NULL;
+
+ frame = avcodec_alloc_frame();
+ frame->nb_samples = audio_input_samples;
+ frame->format = c->sample_fmt;
+ frame->channel_layout = c->channel_layout;
AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples);
audio_time += (double) audio_input_samples / (double) c->sample_rate;
- pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer);
+ if(audio_deinterleave) {
+ int channel, i;
+ uint8_t* temp;
+
+ for(channel = 0; channel < c->channels; channel++) {
+ for(i = 0; i < frame->nb_samples; i++) {
+ memcpy(audio_deinterleave_buffer + (i + channel * frame->nb_samples) * audio_sample_size,
+ audio_input_buffer + (c->channels * i + channel) * audio_sample_size, audio_sample_size);
+ }
+ }
+
+ temp = audio_deinterleave_buffer;
+ audio_deinterleave_buffer = audio_input_buffer;
+ audio_input_buffer = temp;
+ }
+
+ avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, audio_input_buffer,
+ audio_input_samples * c->channels * audio_sample_size, 0);
- if (pkt.size < 0) {
+ if(avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) {
// XXX error("Error writing audio packet");
return -1;
}
- pkt.data = audio_output_buffer;
+ if(got_output) {
+ if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
+ pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base);
+ PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
+ }
- if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
- pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base);
- PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
- }
+ pkt.stream_index = audio_stream->index;
- pkt.stream_index = audio_stream->index;
+ pkt.flags |= AV_PKT_FLAG_KEY;
- pkt.flags |= AV_PKT_FLAG_KEY;
+ if (av_interleaved_write_frame(outfile, &pkt) != 0) {
+ fprintf(stderr, "Error writing audio packet!\n");
+ return -1;
+ }
- if (av_interleaved_write_frame(outfile, &pkt) != 0) {
- fprintf(stderr, "Error writing audio packet!\n");
- return -1;
+ av_free_packet(&pkt);
}
+
+ avcodec_free_frame(&frame);
+
return 0;
}
#endif // #ifdef WITH_AUDASPACE
@@ -608,8 +639,6 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
return st;
}
-/* Prepare an audio stream for the output file */
-
static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size)
{
AVStream *st;
@@ -659,11 +688,6 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
}
}
- if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) {
- BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size);
- return NULL;
- }
-
if (codec->supported_samplerates) {
const int *p = codec->supported_samplerates;
int best = 0;
@@ -692,24 +716,23 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex
st->codec->time_base.num = 1;
st->codec->time_base.den = st->codec->sample_rate;
- audio_outbuf_size = FF_MIN_BUFFER_SIZE;
-
- if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
- audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels;
+ if (c->frame_size == 0)
+ // used to be if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD))
+ // not sure if that is needed anymore, so let's try out if there are any
+ // complaints regarding some ffmpeg versions users might have
+ audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels;
else {
audio_input_samples = c->frame_size;
- if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size)
- audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4;
}
- audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size);
+ audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt);
- if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
- audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float));
- }
- else {
- audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t));
- }
+ audio_sample_size = av_get_bytes_per_sample(c->sample_fmt);
+
+ audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
+
+ if(audio_deinterleave)
+ audio_deinterleave_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size);
audio_time = 0.0f;
@@ -1010,12 +1033,28 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty,
AVCodecContext *c = audio_stream->codec;
AUD_DeviceSpecs specs;
specs.channels = c->channels;
- if (c->sample_fmt == AV_SAMPLE_FMT_FLT) {
- specs.format = AUD_FORMAT_FLOAT32;
- }
- else {
+
+ switch(av_get_packed_sample_fmt(c->sample_fmt))
+ {
+ case AV_SAMPLE_FMT_U8:
+ specs.format = AUD_FORMAT_U8;
+ break;
+ case AV_SAMPLE_FMT_S16:
specs.format = AUD_FORMAT_S16;
+ break;
+ case AV_SAMPLE_FMT_S32:
+ specs.format = AUD_FORMAT_S32;
+ break;
+ case AV_SAMPLE_FMT_FLT:
+ specs.format = AUD_FORMAT_FLOAT32;
+ break;
+ case AV_SAMPLE_FMT_DBL:
+ specs.format = AUD_FORMAT_FLOAT64;
+ break;
+ default:
+ return -31415;
}
+
specs.rate = rd->ffcodecdata.audio_mixrate;
audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume);
#ifdef FFMPEG_CODEC_TIME_BASE
@@ -1138,15 +1177,16 @@ static void end_ffmpeg_impl(int is_autosplit)
MEM_freeN(video_buffer);
video_buffer = 0;
}
- if (audio_output_buffer) {
- av_free(audio_output_buffer);
- audio_output_buffer = 0;
- }
if (audio_input_buffer) {
av_free(audio_input_buffer);
audio_input_buffer = 0;
}
+ if (audio_deinterleave_buffer) {
+ av_free(audio_deinterleave_buffer);
+ audio_deinterleave_buffer = 0;
+ }
+
if (img_convert_ctx) {
sws_freeContext(img_convert_ctx);
img_convert_ctx = 0;