diff options
author | Joerg Mueller <nexyon@gmail.com> | 2010-02-08 02:41:17 +0300 |
---|---|---|
committer | Joerg Mueller <nexyon@gmail.com> | 2010-02-08 02:41:17 +0300 |
commit | 9827a3e9eac70f68db6dc16d03016c51b7ece3f0 (patch) | |
tree | 8825b454008d3b97a64018884c179ea94874af44 /source/blender/blenkernel | |
parent | 2f72b91a54faa7cfbdfd97eff608c8911df1d221 (diff) |
2.5 Audio:
- recode of the whole sequencer audio handling
- encode audio flag removed, instead you choose None as audio codec, added None for video codec too
- ffmpeg formats/codecs: enabled: theora, ogg, vorbis; added: matroska, flac (not working, who can fix?), mp3, wav
- sequencer wave drawing
- volume animation (now also working when mixing down to a file!)
- made sequencer strip position and length values unanimatable
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_sequencer.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_sound.h | 27 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_writeffmpeg.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/sequencer.c | 90 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/sound.c | 293 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/writeffmpeg.c | 170 |
7 files changed, 239 insertions, 358 deletions
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 0c84d729d47..49afe201c92 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -150,8 +150,8 @@ struct ImBuf *give_ibuf_seq(struct Scene *scene, int rectx, int recty, int cfra, struct ImBuf *give_ibuf_seq_threaded(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size); struct ImBuf *give_ibuf_seq_direct(struct Scene *scene, int rectx, int recty, int cfra, int render_size, struct Sequence *seq); void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, int render_size); -void calc_sequence(struct Sequence *seq); -void calc_sequence_disp(struct Sequence *seq); +void calc_sequence(struct Scene *scene, struct Sequence *seq); +void calc_sequence_disp(struct Scene *scene, struct Sequence *seq); void new_tstripdata(struct Sequence *seq); void reload_sequence_new_file(struct Scene *scene, struct Sequence * seq); void sort_seq(struct Scene *scene); @@ -191,8 +191,8 @@ int shuffle_seq_time(ListBase * seqbasep, struct Scene *evil_scene); int seqbase_isolated_sel_check(struct ListBase *seqbase); void free_imbuf_seq(struct Scene *scene, struct ListBase * seqbasep, int check_mem_usage); -void seq_update_sound(struct Sequence *seq); -void seq_update_muting(struct Editing *ed); +void seq_update_sound(struct Scene* scene, struct Sequence *seq); +void seq_update_muting(struct Scene* scene, struct Editing *ed); void seqbase_sound_reload(Scene *scene, ListBase *seqbase); void clear_scene_in_allseqs(struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 82ef525ba91..1c9a7db03c3 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -36,6 +36,7 @@ struct bSound; struct bContext; struct ListBase; struct Main; +struct Sequence; void sound_init(); @@ -63,20 +64,28 @@ void sound_load(struct Main *main, struct bSound* sound); void sound_free(struct bSound* sound); -void sound_unlink(struct bContext *C, struct bSound* sound); +#ifdef AUD_CAPI +AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); +#endif -struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip); +void sound_create_scene(struct Scene *scene); -void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle); +void sound_destroy_scene(struct Scene *scene); -void sound_update_playing(struct bContext *C); +void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip); -void sound_scrub(struct bContext *C); +void sound_remove_scene_sound(struct Scene *scene, void* handle); -#ifdef AUD_CAPI -AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume); -#endif +void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute); + +void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip); + +void sound_play_scene(struct Scene *scene); + +void sound_stop_scene(struct Scene *scene); + +void sound_seek_scene(struct bContext *C); -void sound_stop_all(struct bContext *C); +int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length); #endif diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 98c385ea2e1..20c5b2fd46f 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -45,6 +45,8 @@ extern "C" { #define FFMPEG_FLV 8 #define FFMPEG_MKV 9 #define FFMPEG_OGG 10 +#define FFMPEG_WAV 11 +#define FFMPEG_MP3 12 #define FFMPEG_PRESET_NONE 0 #define FFMPEG_PRESET_DVD 1 diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b80f22a05c2..780ded2a941 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -83,6 +83,7 @@ #include "BKE_sequencer.h" #include "BKE_world.h" #include "BKE_utildefines.h" +#include "BKE_sound.h" //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" @@ -233,6 +234,8 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type) } } + sound_create_scene(scen); + return scen; } @@ -315,6 +318,8 @@ void free_scene(Scene *sce) if(sce->stats) MEM_freeN(sce->stats); + + sound_destroy_scene(sce); } Scene *add_scene(char *name) @@ -480,6 +485,8 @@ Scene *add_scene(char *name) sce->gm.flag = GAME_DISPLAY_LISTS; sce->gm.matmode = GAME_MAT_MULTITEX; + sound_create_scene(sce); + return sce; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 9fde0730011..8c119eb753b 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -233,8 +233,8 @@ void seq_free_sequence(Scene *scene, Sequence *seq) if (ed->act_seq==seq) ed->act_seq= NULL; - if(seq->sound_handle) - sound_delete_handle(scene, seq->sound_handle); + if(seq->scene_sound) + sound_remove_scene_sound(scene, seq->scene_sound); } MEM_freeN(seq); @@ -484,7 +484,7 @@ void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq, } -void calc_sequence_disp(Sequence *seq) +void calc_sequence_disp(Scene *scene, Sequence *seq) { if(seq->startofs && seq->startstill) seq->startstill= 0; if(seq->endofs && seq->endstill) seq->endstill= 0; @@ -500,10 +500,10 @@ void calc_sequence_disp(Sequence *seq) seq->handsize= (float)((seq->enddisp-seq->startdisp)/25); } - seq_update_sound(seq); + seq_update_sound(scene, seq); } -void calc_sequence(Sequence *seq) +void calc_sequence(Scene *scene, Sequence *seq) { Sequence *seqm; int min, max; @@ -511,7 +511,7 @@ void calc_sequence(Sequence *seq) /* check all metas recursively */ seqm= seq->seqbase.first; while(seqm) { - if(seqm->seqbase.first) calc_sequence(seqm); + if(seqm->seqbase.first) calc_sequence(scene, seqm); seqm= seqm->next; } @@ -534,7 +534,7 @@ void calc_sequence(Sequence *seq) seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); seq->len= seq->enddisp - seq->startdisp; } else { - calc_sequence_disp(seq); + calc_sequence_disp(scene, seq); } if(seq->strip && seq->len!=seq->strip->len) { @@ -563,7 +563,7 @@ void calc_sequence(Sequence *seq) } } } - calc_sequence_disp(seq); + calc_sequence_disp(scene, seq); } } @@ -614,7 +614,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) } seq->strip->len = seq->len; } else if (seq->type == SEQ_SOUND) { - seq->len = AUD_getInfo(seq->sound->handle).length * FPS; + seq->len = AUD_getInfo(seq->sound->playback_handle).length * FPS; seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; if (seq->len < 0) { @@ -653,7 +653,7 @@ void reload_sequence_new_file(Scene *scene, Sequence * seq) free_proxy_seq(seq); - calc_sequence(seq); + calc_sequence(scene, seq); } void sort_seq(Scene *scene) @@ -3189,7 +3189,7 @@ static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *chan } if(len_change) - calc_sequence(seq); + calc_sequence(scene, seq); } return free_imbuf; @@ -3239,23 +3239,6 @@ static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) } #endif -static int seq_sound_reload_cb(Sequence *seq, void *arg_pt) -{ - if (seq->type==SEQ_SOUND && seq->sound) { - Scene *scene= (Scene *)arg_pt; - if(seq->sound_handle) - sound_delete_handle(scene, seq->sound_handle); - - seq->sound_handle = sound_new_handle(scene, seq->sound, seq->start, seq->start + seq->strip->len, 0); - return 0; - } - return 1; /* recurse meta's */ -} -void seqbase_sound_reload(Scene *scene, ListBase *seqbase) -{ - seqbase_recursive_apply(seqbase, seq_sound_reload_cb, (void *)scene); -} - /* seq funcs's for transforming internally notice the difference between start/end and left/right. @@ -3463,7 +3446,7 @@ static void seq_translate(Scene *evil_scene, Sequence *seq, int delta) } } - calc_sequence_disp(seq); + calc_sequence_disp(evil_scene, seq); } /* return 0 if there werent enough space */ @@ -3471,13 +3454,13 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene) { int orig_machine= test->machine; test->machine++; - calc_sequence(test); + calc_sequence(evil_scene, test); while( seq_test_overlap(seqbasep, test) ) { if(test->machine >= MAXSEQ) { break; } test->machine++; - calc_sequence(test); // XXX - I dont think this is needed since were only moving vertically, Campbell. + calc_sequence(evil_scene, test); // XXX - I dont think this is needed since were only moving vertically, Campbell. } @@ -3497,7 +3480,7 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test, Scene *evil_scene) new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */ seq_translate(evil_scene, test, new_frame - test->start); - calc_sequence(test); + calc_sequence(evil_scene, test); return 0; } else { return 1; @@ -3526,7 +3509,7 @@ static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir) return offset; } -static int shuffle_seq_time_offset(ListBase * seqbasep, char dir) +static int shuffle_seq_time_offset(Scene* scene, ListBase * seqbasep, char dir) { int ofs= 0; int tot_ofs= 0; @@ -3545,7 +3528,7 @@ static int shuffle_seq_time_offset(ListBase * seqbasep, char dir) for(seq= seqbasep->first; seq; seq= seq->next) { if(seq->tmp) - calc_sequence_disp(seq); /* corrects dummy startdisp/enddisp values */ + calc_sequence_disp(scene, seq); /* corrects dummy startdisp/enddisp values */ } return tot_ofs; @@ -3557,8 +3540,8 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene) Sequence *seq; - int offset_l = shuffle_seq_time_offset(seqbasep, 'L'); - int offset_r = shuffle_seq_time_offset(seqbasep, 'R'); + int offset_l = shuffle_seq_time_offset(evil_scene, seqbasep, 'L'); + int offset_r = shuffle_seq_time_offset(evil_scene, seqbasep, 'R'); int offset = (-offset_l < offset_r) ? offset_l:offset_r; if(offset) { @@ -3573,19 +3556,16 @@ int shuffle_seq_time(ListBase * seqbasep, Scene *evil_scene) return offset? 0:1; } -void seq_update_sound(Sequence *seq) +void seq_update_sound(Scene* scene, Sequence *seq) { - if(seq->type == SEQ_SOUND && seq->sound_handle) + if(seq->scene_sound) { - seq->sound_handle->startframe = seq->startdisp; - seq->sound_handle->endframe = seq->enddisp; - seq->sound_handle->frameskip = seq->startofs + seq->anim_startofs; - seq->sound_handle->changed = -1; + sound_move_scene_sound(scene, seq->scene_sound, seq->startdisp, seq->enddisp, seq->startofs + seq->anim_startofs); /* mute is set in seq_update_muting_recursive */ } } -static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, int mute) +static void seq_update_muting_recursive(Scene *scene, ListBase *seqbasep, Sequence *metaseq, int mute) { Sequence *seq; int seqmute; @@ -3601,27 +3581,26 @@ static void seq_update_muting_recursive(ListBase *seqbasep, Sequence *metaseq, i if(seq == metaseq) seqmute= 0; - seq_update_muting_recursive(&seq->seqbase, metaseq, seqmute); + seq_update_muting_recursive(scene, &seq->seqbase, metaseq, seqmute); } else if(seq->type == SEQ_SOUND) { - if(seq->sound_handle && seqmute != seq->sound_handle->mute) { - seq->sound_handle->mute = seqmute; - seq->sound_handle->changed = -1; + if(seq->scene_sound) { + sound_mute_scene_sound(scene, seq->scene_sound, seqmute); } } } } -void seq_update_muting(Editing *ed) +void seq_update_muting(Scene *scene, Editing *ed) { if(ed) { /* mute all sounds up to current metastack list */ MetaStack *ms= ed->metastack.last; if(ms) - seq_update_muting_recursive(&ed->seqbase, ms->parseq, 1); + seq_update_muting_recursive(scene, &ed->seqbase, ms->parseq, 1); else - seq_update_muting_recursive(&ed->seqbase, NULL, 0); + seq_update_muting_recursive(scene, &ed->seqbase, NULL, 0); } } @@ -3744,6 +3723,7 @@ Sequence *alloc_sequence(ListBase *lb, int cfra, int machine) seq->machine= machine; seq->mul= 1.0; seq->blend_opacity = 100.0; + seq->volume = 1.0f; return seq; } @@ -3793,13 +3773,13 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo sound = sound_new_file(CTX_data_main(C), seq_load->path); - if (sound==NULL || sound->handle == NULL) { + if (sound==NULL || sound->playback_handle == NULL) { //if(op) // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); return NULL; } - info = AUD_getInfo(sound->handle); + info = AUD_getInfo(sound->playback_handle); if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(C, sound); @@ -3824,9 +3804,9 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); - seq->sound_handle = sound_new_handle(scene, sound, seq_load->start_frame, seq_load->start_frame + strip->len, 0); + seq->scene_sound = sound_add_scene_sound(scene, seq, seq_load->start_frame, seq_load->start_frame + strip->len, 0); - calc_sequence_disp(seq); + calc_sequence_disp(scene, seq); /* last active name */ strncpy(ed->act_sounddir, strip->dir, FILE_MAXDIR-1); @@ -3868,7 +3848,7 @@ Sequence *sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo BLI_split_dirfile_basic(seq_load->path, strip->dir, se->name); - calc_sequence_disp(seq); + calc_sequence_disp(scene, seq); if(seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 1be59529cc7..7b451bd5a98 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -12,6 +12,7 @@ #include "BLI_blenlib.h" #include "DNA_scene_types.h" +#include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_packedFile_types.h" #include "DNA_screen_types.h" @@ -26,6 +27,9 @@ #include "BKE_context.h" #include "BKE_library.h" #include "BKE_packedFile.h" +#include "BKE_fcurve.h" + +#include "RNA_access.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -107,7 +111,7 @@ struct bSound* sound_new_file(struct Main *main, char* filename) sound_load(main, sound); - if(!sound->handle) + if(!sound->playback_handle) { free_libblock(&main->sound, sound); sound = NULL; @@ -133,7 +137,7 @@ struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source) sound_load(CTX_data_main(C), sound); - if(!sound->handle) + if(!sound->playback_handle) { free_libblock(&CTX_data_main(C)->sound, sound); sound = NULL; @@ -159,7 +163,7 @@ struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, floa sound_load(CTX_data_main(C), sound); - if(!sound->handle) + if(!sound->playback_handle) { free_libblock(&CTX_data_main(C)->sound, sound); sound = NULL; @@ -175,8 +179,6 @@ void sound_delete(struct bContext *C, struct bSound* sound) { sound_free(sound); - sound_unlink(C, sound); - free_libblock(&CTX_data_main(C)->sound, sound); } } @@ -187,7 +189,7 @@ void sound_cache(struct bSound* sound, int ignore) AUD_unload(sound->cache); sound->cache = AUD_bufferSound(sound->handle); - sound->changed++; + sound->playback_handle = sound->cache; } void sound_delete_cache(struct bSound* sound) @@ -196,6 +198,7 @@ void sound_delete_cache(struct bSound* sound) { AUD_unload(sound->cache); sound->cache = NULL; + sound->playback_handle = sound->handle; } } @@ -207,6 +210,7 @@ void sound_load(struct Main *main, struct bSound* sound) { AUD_unload(sound->handle); sound->handle = NULL; + sound->playback_handle = NULL; } // XXX unused currently @@ -253,7 +257,10 @@ void sound_load(struct Main *main, struct bSound* sound) break; } #endif - sound->changed++; + if(sound->cache) + sound->playback_handle = sound->cache; + else + sound->playback_handle = sound->handle; } } @@ -269,243 +276,115 @@ void sound_free(struct bSound* sound) { AUD_unload(sound->handle); sound->handle = NULL; + sound->playback_handle = NULL; } } -void sound_unlink(struct bContext *C, struct bSound* sound) +static float sound_get_volume(Scene* scene, Sequence* sequence, float time) { - Scene *scene; - SoundHandle *handle; - -// XXX unused currently -#if 0 - bSound *snd; - for(snd = CTX_data_main(C)->sound.first; snd; snd = snd->id.next) - { - if(snd->child_sound == sound) - { - snd->child_sound = NULL; - if(snd->handle) - { - AUD_unload(sound->handle); - snd->handle = NULL; - } - - sound_unlink(C, snd); - } - } -#endif - - for(scene = CTX_data_main(C)->scene.first; scene; scene = scene->id.next) - { - for(handle = scene->sound_handles.first; handle; handle = handle->next) - { - if(handle->source == sound) - { - handle->source = NULL; - if(handle->handle) - AUD_stop(handle->handle); - } - } - } + struct FCurve* fcu = id_data_find_fcurve(scene, sequence, &RNA_Sequence, "volume", 0); + if(fcu) + return evaluate_fcurve(fcu, time * FPS); + else + return sequence->volume; } -struct SoundHandle* sound_new_handle(struct Scene *scene, struct bSound* sound, int startframe, int endframe, int frameskip) +AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume) { - ListBase* handles = &scene->sound_handles; + AUD_Device* mixdown = AUD_openReadDevice(specs); + + AUD_setDeviceVolume(mixdown, volume); - SoundHandle* handle = MEM_callocN(sizeof(SoundHandle), "sound_handle"); - handle->source = sound; - handle->startframe = startframe; - handle->endframe = endframe; - handle->frameskip = frameskip; - handle->state = AUD_STATUS_INVALID; - handle->volume = 1.0f; + AUD_playDevice(mixdown, scene->sound_scene, start / FPS); - BLI_addtail(handles, handle); + return mixdown; +} - return handle; +void sound_create_scene(struct Scene *scene) +{ + scene->sound_scene = AUD_createSequencer(scene, (AUD_volumeFunction)&sound_get_volume); } -void sound_delete_handle(struct Scene *scene, struct SoundHandle *handle) +void sound_destroy_scene(struct Scene *scene) { - if(handle == NULL) - return; + if(scene->sound_scene_handle) + AUD_stop(scene->sound_scene_handle); + if(scene->sound_scene) + AUD_destroySequencer(scene->sound_scene); +} - if(handle->handle) - AUD_stop(handle->handle); +void* sound_add_scene_sound(struct Scene *scene, struct Sequence* sequence, int startframe, int endframe, int frameskip) +{ + return AUD_addSequencer(scene->sound_scene, &(sequence->sound->playback_handle), startframe / FPS, endframe / FPS, frameskip / FPS, sequence); +} - BLI_freelinkN(&scene->sound_handles, handle); +void sound_remove_scene_sound(struct Scene *scene, void* handle) +{ + AUD_removeSequencer(scene->sound_scene, handle); } -void sound_stop_all(struct bContext *C) +void sound_mute_scene_sound(struct Scene *scene, void* handle, char mute) { - SoundHandle *handle; + AUD_muteSequencer(scene->sound_scene, handle, mute); +} - for(handle = CTX_data_scene(C)->sound_handles.first; handle; handle = handle->next) - { - if(handle->state == AUD_STATUS_PLAYING) - { - AUD_pause(handle->handle); - handle->state = AUD_STATUS_PAUSED; - } - } +void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, int endframe, int frameskip) +{ + AUD_moveSequencer(scene->sound_scene, handle, startframe / FPS, endframe / FPS, frameskip / FPS); } -void sound_update_playing(struct bContext *C) +void sound_start_play_scene(struct Scene *scene) { - SoundHandle *handle; - Scene* scene = CTX_data_scene(C); - int cfra = CFRA; - float fps = FPS; - int action; + AUD_Sound* sound; + sound = AUD_loopSound(scene->sound_scene); + scene->sound_scene_handle = AUD_play(sound, 1); + AUD_unload(sound); +} +void sound_play_scene(struct Scene *scene) +{ AUD_lock(); - for(handle = scene->sound_handles.first; handle; handle = handle->next) - { - if(cfra < handle->startframe || cfra >= handle->endframe || handle->mute || (scene->audio.flag & AUDIO_MUTE)) - { - if(handle->state == AUD_STATUS_PLAYING) - { - AUD_pause(handle->handle); - handle->state = AUD_STATUS_PAUSED; - } - } - else - { - action = 0; - - if(handle->changed != handle->source->changed) - { - handle->changed = handle->source->changed; - action = 3; - if(handle->state != AUD_STATUS_INVALID) - { - AUD_stop(handle->handle); - handle->state = AUD_STATUS_INVALID; - } - } - else - { - if(handle->state != AUD_STATUS_PLAYING) - action = 3; - else - { - handle->state = AUD_getStatus(handle->handle); - if(handle->state != AUD_STATUS_PLAYING) - action = 3; - else - { - float diff = AUD_getPosition(handle->handle) * fps - cfra + handle->startframe; - if(diff < 0.0) - diff = -diff; - if(diff > FPS/2.0) - { - action = 2; - } - } - } - } - - AUD_setSoundVolume(handle->handle, handle->volume); - - if(action & 1) - { - if(handle->state == AUD_STATUS_INVALID) - { - if(handle->source && handle->source->handle) - { - AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, handle->frameskip / fps, (handle->frameskip + handle->endframe - handle->startframe)/fps); - handle->handle = AUD_play(limiter, 1); - AUD_unload(limiter); - if(handle->handle) - handle->state = AUD_STATUS_PLAYING; - if(cfra == handle->startframe) - action &= ~2; - } - } - else - if(AUD_resume(handle->handle)) - handle->state = AUD_STATUS_PLAYING; - else - handle->state = AUD_STATUS_INVALID; - } - - if(action & 2) - AUD_seek(handle->handle, (cfra - handle->startframe) / fps); - } - } + if(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID) + sound_start_play_scene(scene); + + AUD_seek(scene->sound_scene_handle, CFRA / FPS); + AUD_setLoop(scene->sound_scene_handle, -1, -1); + AUD_resume(scene->sound_scene_handle); AUD_unlock(); } -void sound_scrub(struct bContext *C) +void sound_stop_scene(struct Scene *scene) { - SoundHandle *handle; - Scene* scene = CTX_data_scene(C); - int cfra = CFRA; - float fps = FPS; - - if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) - { - AUD_lock(); - - for(handle = scene->sound_handles.first; handle; handle = handle->next) - { - if(cfra >= handle->startframe && cfra < handle->endframe && !handle->mute) - { - if(handle->source && handle->source->handle) - { - int frameskip = handle->frameskip + cfra - handle->startframe; - AUD_Sound* limiter = AUD_limitSound(handle->source->cache ? handle->source->cache : handle->source->handle, frameskip / fps, (frameskip + 1)/fps); - AUD_play(limiter, 0); - AUD_unload(limiter); - } - } - } - - AUD_unlock(); - } + AUD_pause(scene->sound_scene_handle); } -AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume) +void sound_seek_scene(struct bContext *C) { - AUD_Device* mixdown = AUD_openReadDevice(specs); - SoundHandle *handle; - float fps = FPS; - AUD_Sound *limiter, *delayer; - int frameskip, s, e; + struct Scene *scene = CTX_data_scene(C); - end++; + AUD_lock(); - AUD_setDeviceVolume(mixdown, volume); + if(!scene->sound_scene_handle || AUD_getStatus(scene->sound_scene_handle) == AUD_STATUS_INVALID) + { + sound_start_play_scene(scene); + AUD_pause(scene->sound_scene_handle); + } - for(handle = scene->sound_handles.first; handle; handle = handle->next) + if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { - if(start < handle->endframe && end > handle->startframe && !handle->mute && handle->source && handle->source->handle) - { - frameskip = handle->frameskip; - s = handle->startframe - start; - e = handle->frameskip + AUD_MIN(handle->endframe, end) - handle->startframe; - - if(s < 0) - { - frameskip -= s; - s = 0; - } - - AUD_setSoundVolume(handle->handle, handle->volume); - - limiter = AUD_limitSound(handle->source->handle, frameskip / fps, e / fps); - delayer = AUD_delaySound(limiter, s / fps); - - AUD_playDevice(mixdown, delayer); - - AUD_unload(delayer); - AUD_unload(limiter); - } + AUD_setLoop(scene->sound_scene_handle, -1, 1 / FPS); + AUD_seek(scene->sound_scene_handle, CFRA / FPS); + AUD_resume(scene->sound_scene_handle); } + else + AUD_seek(scene->sound_scene_handle, CFRA / FPS); - return mixdown; + AUD_unlock(); +} + +int sound_read_sound_buffer(bSound* sound, float* buffer, int length) +{ + AUD_readSound(sound->cache, buffer, length); } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 9c38f84aa26..3aca9ffb4e7 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -15,7 +15,6 @@ * */ - #ifdef WITH_FFMPEG #include <string.h> #include <stdio.h> @@ -78,11 +77,10 @@ extern void do_init_ffmpeg(); static int ffmpeg_type = 0; static int ffmpeg_codec = CODEC_ID_MPEG4; -static int ffmpeg_audio_codec = CODEC_ID_MP2; +static int ffmpeg_audio_codec = CODEC_ID_NONE; static int ffmpeg_video_bitrate = 1150; static int ffmpeg_audio_bitrate = 128; static int ffmpeg_gop_size = 12; -static int ffmpeg_multiplex_audio = 1; static int ffmpeg_autosplit = 0; static int ffmpeg_autosplit_count = 0; @@ -99,6 +97,7 @@ static uint8_t* audio_input_buffer = 0; static int audio_input_frame_size = 0; static uint8_t* audio_output_buffer = 0; static int audio_outbuf_size = 0; +static double audio_time = 0.0f; static AUD_Device* audio_mixdown_device = 0; @@ -130,30 +129,43 @@ static int write_audio_frame(void) { AVCodecContext* c = NULL; AVPacket pkt; + AVStream* str = audio_stream; c = get_codec_from_stream(audio_stream); - if(audio_mixdown_device) - AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_frame_size); - av_init_packet(&pkt); + pkt.size = 0; + + AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_frame_size); + audio_time += (double) audio_input_frame_size / (double) c->sample_rate; pkt.size = avcodec_encode_audio(c, audio_output_buffer, - audio_outbuf_size, + audio_outbuf_size, (short*) audio_input_buffer); + + if(pkt.size <= 0) + { + // XXX error("Error writing audio packet"); + return -1; + } + pkt.data = audio_output_buffer; + + if(c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) + { #ifdef FFMPEG_CODEC_TIME_BASE - pkt.pts = av_rescale_q(c->coded_frame->pts, - c->time_base, audio_stream->time_base); + pkt.pts = av_rescale_q(c->coded_frame->pts, + c->time_base, audio_stream->time_base); #else - pkt.pts = c->coded_frame->pts; + pkt.pts = c->coded_frame->pts; #endif - fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts); + fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts); + } pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_interleaved_write_frame(outfile, &pkt) != 0) { - //XXX error("Error writing audio packet"); + // XXX error("Error writing audio packet"); return -1; } return 0; @@ -233,6 +245,14 @@ static const char** get_file_extensions(int format) static const char * rv[] = { ".ogg", ".ogv", NULL }; return rv; } + case FFMPEG_MP3: { + static const char * rv[] = { ".mp3", NULL }; + return rv; + } + case FFMPEG_WAV: { + static const char * rv[] = { ".wav", NULL }; + return rv; + } default: return NULL; } @@ -563,6 +583,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->sample_rate = rd->ffcodecdata.audio_mixrate; c->bit_rate = ffmpeg_audio_bitrate*1000; + c->sample_fmt = SAMPLE_FMT_S16; c->channels = 2; codec = avcodec_find_encoder(c->codec_id); if (!codec) { @@ -577,40 +598,22 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex return NULL; } - /* FIXME: Should be user configurable */ - if (ffmpeg_type == FFMPEG_DV) { - /* this is a hack around the poor ffmpeg dv multiplexer. */ - /* only fixes PAL for now - (NTSC is a lot more complicated here...)! */ - audio_outbuf_size = 7680; - } else { - audio_outbuf_size = 10000; - } + audio_outbuf_size = FF_MIN_BUFFER_SIZE; + audio_output_buffer = (uint8_t*)MEM_mallocN( audio_outbuf_size, "FFMPEG audio encoder input buffer"); - /* ugly hack for PCM codecs */ - - if (c->frame_size <= 1) { - audio_input_frame_size = audio_outbuf_size / c->channels; - switch(c->codec_id) { - case CODEC_ID_PCM_S16LE: - case CODEC_ID_PCM_S16BE: - case CODEC_ID_PCM_U16LE: - case CODEC_ID_PCM_U16BE: - audio_input_frame_size >>= 1; - break; - default: - break; - } - } else { + if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD)) + audio_input_frame_size = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels; + else audio_input_frame_size = c->frame_size; - } audio_input_buffer = (uint8_t*)MEM_mallocN( - audio_input_frame_size * sizeof(short) * c->channels, + audio_input_frame_size * c->channels * sizeof(int16_t), "FFMPEG audio encoder output buffer"); + audio_time = 0.0f; + return st; } /* essential functions -- start, append, end */ @@ -629,8 +632,6 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; ffmpeg_gop_size = rd->ffcodecdata.gop_size; - ffmpeg_multiplex_audio = rd->ffcodecdata.flags - & FFMPEG_MULTIPLEX_AUDIO; ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; @@ -641,12 +642,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report fprintf(stderr, "Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" - " gop_size=%d, multiplex=%d, autosplit=%d\n" + " gop_size=%d, autosplit=%d\n" " render width=%d, render height=%d\n", name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec, ffmpeg_video_bitrate, ffmpeg_audio_bitrate, - ffmpeg_gop_size, ffmpeg_multiplex_audio, - ffmpeg_autosplit, rectx, recty); + ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty); exts = get_file_extensions(ffmpeg_type); if (!exts) { @@ -667,7 +667,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report of->oformat = fmt; of->packet_size= rd->ffcodecdata.mux_packet_size; - if (ffmpeg_multiplex_audio) { + if (ffmpeg_audio_codec != CODEC_ID_NONE) { of->mux_rate = rd->ffcodecdata.mux_rate; } else { of->mux_rate = 0; @@ -676,6 +676,8 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report of->preload = (int)(0.5*AV_TIME_BASE); of->max_delay = (int)(0.7*AV_TIME_BASE); + fmt->audio_codec = ffmpeg_audio_codec; + snprintf(of->filename, sizeof(of->filename), "%s", name); /* set the codec to the user's selection */ switch(ffmpeg_type) { @@ -703,6 +705,11 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report case FFMPEG_FLV: fmt->video_codec = CODEC_ID_FLV1; break; + case FFMPEG_MP3: + fmt->audio_codec = CODEC_ID_MP3; + case FFMPEG_WAV: + fmt->video_codec = CODEC_ID_NONE; + break; case FFMPEG_MPEG4: default: fmt->video_codec = CODEC_ID_MPEG4; @@ -723,30 +730,29 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } } - fmt->audio_codec = ffmpeg_audio_codec; - if (ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = CODEC_ID_PCM_S16LE; - if (ffmpeg_multiplex_audio && rd->ffcodecdata.audio_mixrate != 48000) { + if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000) { BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!"); return 0; } } - video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); - printf("alloc video stream %p\n", video_stream); - if (!video_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing video stream."); - return 0; + if (fmt->video_codec != CODEC_ID_NONE) { + video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); + printf("alloc video stream %p\n", video_stream); + if (!video_stream) { + BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + return 0; + } } - - if (ffmpeg_multiplex_audio) { + + if (ffmpeg_audio_codec != CODEC_ID_NONE) { audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); if (!audio_stream) { BKE_report(reports, RPT_ERROR, "Error initializing audio stream."); return 0; } - //XXX audiostream_play(SFRA, 0, 1); } if (av_set_parameters(of, NULL) < 0) { BKE_report(reports, RPT_ERROR, "Error setting output parameters."); @@ -818,14 +824,14 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo success = start_ffmpeg_impl(rd, rectx, recty, reports); - if(ffmpeg_multiplex_audio && audio_stream) + if(audio_stream) { AVCodecContext* c = get_codec_from_stream(audio_stream); AUD_DeviceSpecs specs; specs.channels = c->channels; specs.format = AUD_FORMAT_S16; specs.rate = rd->ffcodecdata.audio_mixrate; - audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra, rd->ffcodecdata.audio_volume); + audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); } return success; @@ -833,21 +839,13 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo void end_ffmpeg(void); -static void write_audio_frames() +static void write_audio_frames(double to_pts) { int finished = 0; - while (ffmpeg_multiplex_audio && !finished) { - double a_pts = ((double)audio_stream->pts.val - * audio_stream->time_base.num - / audio_stream->time_base.den); - double v_pts = ((double)video_stream->pts.val - * video_stream->time_base.num - / video_stream->time_base.den); - - if (a_pts < v_pts) { - write_audio_frame(); - } else { + while (audio_stream && !finished) { + if((audio_time >= to_pts) || + (write_audio_frame())) { finished = 1; } } @@ -856,25 +854,31 @@ static void write_audio_frames() int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { AVFrame* avframe; - int success; + int success = 1; fprintf(stderr, "Writing frame %i, " "render width=%d, render height=%d\n", frame, rectx, recty); - write_audio_frames(); +// why is this done before writing the video frame and again at end_ffmpeg? +// write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); - avframe= generate_video_frame((unsigned char*) pixels, reports); - success= (avframe && write_video_frame(rd, avframe, reports)); - - if (ffmpeg_autosplit) { - if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) { - end_ffmpeg(); - ffmpeg_autosplit_count++; - success &= start_ffmpeg_impl(rd, rectx, recty, reports); + if(video_stream) + { + avframe= generate_video_frame((unsigned char*) pixels, reports); + success= (avframe && write_video_frame(rd, avframe, reports)); + + if (ffmpeg_autosplit) { + if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) { + end_ffmpeg(); + ffmpeg_autosplit_count++; + success &= start_ffmpeg_impl(rd, rectx, recty, reports); + } } } + write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); + return success; } @@ -885,9 +889,9 @@ void end_ffmpeg(void) fprintf(stderr, "Closing ffmpeg...\n"); - if (audio_stream && video_stream) { +/* if (audio_stream) { SEE UPPER write_audio_frames(); - } + }*/ if(audio_mixdown_device) { @@ -1259,8 +1263,8 @@ void ffmpeg_verify_image_type(RenderData *rd) } } - if(audio && rd->ffcodecdata.audio_codec <= 0) { - rd->ffcodecdata.audio_codec = CODEC_ID_MP2; + if(audio && rd->ffcodecdata.audio_codec < 0) { + rd->ffcodecdata.audio_codec = CODEC_ID_NONE; rd->ffcodecdata.audio_bitrate = 128; } } |