胡斌

part of refactor the process

... ... @@ -402,18 +402,44 @@ int merge_audio_file(vector<string> & files, const char * dest)
return 0;
}
int process_files(const char * output_dest_file)
{
vector<fileinfo> & filesaudio = media_files[type_audio];
vector<fileinfo> & filesvideo = media_files[type_video];
class MergeProcess{
public:
MergeProcess(vector<fileinfo> & a, vector<fileinfo> & v);
int process_files(const char * output_dest_file);
protected:
void init();
void adjust_va_timestamp();
void merge_left_audio();
int process_video_ahead_of_audio();
int process_video_behind_audio();
int process_video_align_audio();
int process_video_loop();
int process_va();
protected:
vector<fileinfo> & filesaudio;
vector<fileinfo> & filesvideo;
vector<string > merged_files;
vector<string> tmp_files;
int nv = 0;
int nf = 0;
char destfile[1024],audio_file[1024],pic_file[1024];
int nv; // the index of processing video file
int nf;//the index of processing target merged ts
char destfile[1024], audio_file[1024], pic_file[1024];
char blank_pic_file[1024];
char silence_aac_file[1024];
int audio_index;
int audio_start;
fileinfo audio;
fileinfo video;
};
MergeProcess::MergeProcess(vector<fileinfo> & a, vector<fileinfo> & v) :filesaudio(a), filesvideo(v)
{
init();
}
void MergeProcess::init()
{
strcpy(blank_pic_file, cfg_path);
strcat(blank_pic_file, "blank.jpg");
... ... @@ -422,318 +448,365 @@ int process_files(const char * output_dest_file)
check_audio_duration();
get_duration_from_video_file();
//don't split video, for a video, using merged audios to mix with it
//for audio, mix with video or jpg
if (filesvideo.size()) {//has video files
if (filesaudio.size()){
for (int i = 0; i < filesaudio.size(); i++){ //
fileinfo audio = filesaudio[i];
float audio_start = audio.start_time;
nv = 0;
nf = 0;
audio_index = 0;
}
for (int j = i; j < filesaudio.size(); j++){
filesaudio[j].start_time -= audio_start;
filesaudio[j].end_time -= audio_start;
}
void MergeProcess::adjust_va_timestamp()
{
fileinfo audio = filesaudio[audio_index];
float audio_start = audio.start_time;
for (int j = nv; j < filesvideo.size(); j++) {
filesvideo[j].start_time -= audio_start;
filesvideo[j].end_time -= audio_start;
}
for (int j = audio_index; j < filesaudio.size(); j++){
filesaudio[j].start_time -= audio_start;
filesaudio[j].end_time -= audio_start;
}
audio = filesaudio[i];
for (int j = nv; j < filesvideo.size(); j++) {
filesvideo[j].start_time -= audio_start;
filesvideo[j].end_time -= audio_start;
}
}
audio_start = 0;//for a new processing audio,the start is 0
for (; nv < filesvideo.size(); nv++) {
fileinfo video = filesvideo[nv];
void MergeProcess::merge_left_audio()
{
if (audio_start < audio.end_time){
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), audio_start, audio.end_time - audio_start, destfile);
tmp_files.push_back(destfile);
sprintf(destfile, "%d.ts", nf);
if (nv < filesvideo.size()) {
fileinfo video = filesvideo[nv];
sprintf(pic_file, "%s.jpg", video.name.c_str());
get_video_first_frame_jpeg(video, pic_file);
tmp_files.push_back(pic_file);
}
else {
strcpy(pic_file, blank_pic_file);
}
merge_audio_pic(audio, nf, pic_file, destfile);
merged_files.push_back(destfile);
nf++;
}
}
if (video.start_time < audio_start - 0.1)
{//video is much more ahead of audio,try padding silence first
if (video.end_time < audio_start + 0.1) {
sprintf(destfile, "%d_silence.aac", nf);
split_audio(silence_aac_file, 0, video.end_time - video.start_time, destfile);
tmp_files.push_back(destfile);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(destfile, video.name.c_str(), destfile);
merged_files.push_back(destfile);
nf++;
continue; //for next video
}
else {
// combine a audio file for the video
double silence_audio_start = audio.end_time;//maybe need append silence
double silence_audio_end = video.end_time;
bool need_append_silence = true;
bool to_next_video = false;
vector<std::string > merge_audio_files;
sprintf(destfile, "%d_0_silence.aac", nf);//a duration of silence
split_audio(silence_aac_file, 0, audio_start - video.start_time, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
if (audio.end_time < video.end_time + 0.1 && audio.end_time > video.end_time - 0.1) {
merge_audio_files.push_back(audio.name); //whole audio file,just fit
audio_start = audio.end_time + 0.1;
need_append_silence = false;
}
else if (audio.end_time > video.end_time){ //split part of audio file
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
split_audio(audio.name.c_str(), audio_start, video.end_time - audio_start, destfile);
audio_start = video.end_time;
need_append_silence = false;
}
else {
merge_audio_files.push_back(audio.name);
for (; i + 1 < filesaudio.size(); i++){//since video is not finished,try find next audio
audio = filesaudio[i + 1];
if (audio.start_time < video.end_time) {//next audio should split to fit the video
silence_audio_end = audio.start_time;
sprintf(destfile, "%d_%d_silence.aac", nf, i);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
if (audio.end_time > video.end_time - 0.1 && audio.end_time < video.end_time + 0.1) {//just match
merge_audio_files.push_back(audio.name);
need_append_silence = false;
audio_start = audio.end_time + 0.1;
i++;//this audio is used
break;
}
if (audio.end_time > video.end_time){
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
split_audio(audio.name.c_str(), 0, video.end_time - audio.start_time, destfile);
need_append_silence = false;
//adjust timecode for the audio is part left
float cur_audio_start = video.end_time - audio.start_time;
audio_start = audio.start_time;
for (int j = i + 1; j < filesaudio.size(); j++){
filesaudio[j].start_time -= audio_start;
filesaudio[j].end_time -= audio_start;
}
for (int j = nv; j < filesvideo.size(); j++) {
filesvideo[j].start_time -= audio_start;
filesvideo[j].end_time -= audio_start;
}
i++;
audio = filesaudio[i];
audio_start = cur_audio_start;
to_next_video = true;
break;
}
merge_audio_files.push_back(audio.name);//whole audio should be appended
silence_audio_start = audio.end_time; //adjust the silence start
}
else {
break;//no need for next audio
}
}//end audio find for the video
}//end else
if (need_append_silence) {
sprintf(destfile, "%d_silence.aac", nf);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
}
sprintf(audio_file, "%d_merged.aac", nf);
merge_audio_file(merge_audio_files, audio_file);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio_file, video.name.c_str(), destfile);
merged_files.push_back(destfile);
nf++;
if (!to_next_video){
nv++;//this video is processed
break;
}
}//end need combine
}//end video is ahead of audio
//-----VS-----
//AS----------
if (video.start_time - audio_start > 0.1) {//video is behind audio too much
sprintf(audio_file, "%d_%s", nf, audio.name.c_str());
if (video.start_time < audio.end_time - 0.1){
split_audio(audio.name.c_str(), audio_start, video.start_time - audio_start, audio_file);
audio_start = video.start_time;
}
else {
split_audio(audio.name.c_str(), audio_start, audio.end_time - audio_start, audio_file);
}
tmp_files.push_back(audio_file);
int MergeProcess::process_video_ahead_of_audio()
{
if (video.end_time < audio_start + 0.1) {
sprintf(destfile, "%d_silence.aac", nf);
split_audio(silence_aac_file, 0, video.end_time - video.start_time, destfile);
tmp_files.push_back(destfile);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(destfile, video.name.c_str(), destfile);
merged_files.push_back(destfile);
nf++;
return 0; //for next video
}
else {
// combine a audio file for the video
double silence_audio_start = audio.end_time;//maybe need append silence
double silence_audio_end = video.end_time;
bool need_append_silence = true;
bool to_next_video = false;
vector<std::string > merge_audio_files;
sprintf(destfile, "%d_0_silence.aac", nf);//a duration of silence
split_audio(silence_aac_file, 0, audio_start - video.start_time, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
if (audio.end_time < video.end_time + 0.1 && audio.end_time > video.end_time - 0.1) {
merge_audio_files.push_back(audio.name); //whole audio file,just fit
audio_start = audio.end_time + 0.1;
need_append_silence = false;
}
else if (audio.end_time > video.end_time){ //split part of audio file
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
split_audio(audio.name.c_str(), audio_start, video.end_time - audio_start, destfile);
audio_start = video.end_time;
need_append_silence = false;
}
else {
merge_audio_files.push_back(audio.name);
sprintf(pic_file, "%s.jpg", video.name.c_str());
get_video_first_frame_jpeg(video, pic_file);
tmp_files.push_back(pic_file);
for (; audio_index + 1 < filesaudio.size(); audio_index++){//since video is not finished,try find next audio
audio = filesaudio[audio_index + 1];
if (audio.start_time < video.end_time) {//next audio should split to fit the video
silence_audio_end = audio.start_time;
sprintf(destfile, "%d.ts", nf);
merge_audio_pic(audio_file, pic_file, destfile);
merged_files.push_back(destfile);
nf++;
sprintf(destfile, "%d_%d_silence.aac", nf, audio_index);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
if (video.start_time >= audio.end_time - 0.1){//all audio file no video, to next audio
audio_start = audio.end_time + 0.1;//no audio left
break;
}
if (audio.end_time > video.end_time - 0.1 && audio.end_time < video.end_time + 0.1) {//just match
merge_audio_files.push_back(audio.name);
need_append_silence = false;
audio_start = audio.end_time + 0.1;
audio_index++;//this audio is used
break;
}
//----AS--------
//----VS--------
else if (audio_start - video.start_time < 0.1){
if (audio.end_time > video.end_time){ //this video finish, to next video
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), video.start_time, video.end_time - video.start_time, destfile);
tmp_files.push_back(destfile);
audio_start = video.end_time;
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio, nf, video, destfile);
merged_files.push_back(destfile);
nf++;
}
else if (video.end_time - audio.end_time < 0.1){//just fine, this audio file finish
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), video.start_time, audio.end_time - video.start_time, destfile);
tmp_files.push_back(destfile);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio, nf, video, destfile);
merged_files.push_back(destfile);
audio_start = audio.end_time + 0.1;//no audio left
nf++;
nv++;//this video is used
break;
if (audio.end_time > video.end_time){
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
split_audio(audio.name.c_str(), 0, video.end_time - audio.start_time, destfile);
need_append_silence = false;
//adjust timecode for the audio is part left
float cur_audio_start = video.end_time - audio.start_time;
audio_start = audio.start_time;
for (int j = audio_index + 1; j < filesaudio.size(); j++){
filesaudio[j].start_time -= audio_start;
filesaudio[j].end_time -= audio_start;
}
else { // this audio finish,add silence and/or next audio
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), video.start_time, audio.end_time - video.start_time, destfile);
vector<std::string > merge_audio_files;
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
audio_start = audio.end_time + 0.1;
double silence_audio_start = audio.end_time;
double silence_audio_end = video.end_time;
bool need_silence = true;
bool to_next_video = false;
for (; i + 1 < filesaudio.size(); i++){//since video is not finished,try find next audio
audio = filesaudio[i + 1];
if (audio.start_time < video.end_time) {//next audio should split to fit the video
silence_audio_end = audio.start_time;
sprintf(destfile, "%d_%d_silence.aac", nf, i);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
if (audio.end_time > video.end_time - 0.1 && audio.end_time < video.end_time + 0.1) {//just match
merge_audio_files.push_back(audio.name);
need_silence = false;
audio_start = audio.end_time + 0.1;
i++;
break;
}
if (audio.end_time > video.end_time){
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
split_audio(audio.name.c_str(), 0, video.end_time - audio.start_time, destfile);
need_silence = false;
//adjust timecode for the audio is part left
float cur_audio_start = video.end_time - audio.start_time;
audio_start = audio.start_time;
for (int j = i + 1; j < filesaudio.size(); j++){
filesaudio[j].start_time -= audio_start;
filesaudio[j].end_time -= audio_start;
}
for (int j = nv; j < filesvideo.size(); j++) {
filesvideo[j].start_time -= audio_start;
filesvideo[j].end_time -= audio_start;
}
i++;
audio = filesaudio[i];
audio_start = cur_audio_start;
to_next_video = true;
break;
}
merge_audio_files.push_back(audio.name);//whole audio should be appended
silence_audio_start = audio.end_time; //adjust the silence start
audio_start = audio.end_time + 0.1;
}
else {
break;//no need for next audio
}
}
if (need_silence) {
sprintf(destfile, "%d_silence.aac", nf);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
}
sprintf(audio_file, "%d_merged.aac", nf);
merge_audio_file(merge_audio_files, audio_file);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio_file, video.name.c_str(), destfile);
merged_files.push_back(destfile);
nf++;
if (!to_next_video){
nv++;
break;
}
for (int j = nv; j < filesvideo.size(); j++) {
filesvideo[j].start_time -= audio_start;
filesvideo[j].end_time -= audio_start;
}
audio_index++;
audio = filesaudio[audio_index];
audio_start = cur_audio_start;
to_next_video = true;
break;
}
merge_audio_files.push_back(audio.name);//whole audio should be appended
silence_audio_start = audio.end_time; //adjust the silence start
}
else {
break;//no need for next audio
}
}//end audio find for the video
}//end else
if (need_append_silence) {
sprintf(destfile, "%d_silence.aac", nf);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
}
sprintf(audio_file, "%d_merged.aac", nf);
merge_audio_file(merge_audio_files, audio_file);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio_file, video.name.c_str(), destfile);
merged_files.push_back(destfile);
nf++;
if (!to_next_video){
nv++;//this video is processed
return 1;
}
}//end need combine
return 0;
}
int MergeProcess::process_video_behind_audio()
{
sprintf(audio_file, "%d_%s", nf, audio.name.c_str());
if (video.start_time < audio.end_time - 0.1){
split_audio(audio.name.c_str(), audio_start, video.start_time - audio_start, audio_file);
audio_start = video.start_time;
}
else {
split_audio(audio.name.c_str(), audio_start, audio.end_time - audio_start, audio_file);
}
tmp_files.push_back(audio_file);
sprintf(pic_file, "%s.jpg", video.name.c_str());
get_video_first_frame_jpeg(video, pic_file);
tmp_files.push_back(pic_file);
if (audio_start < audio.end_time){
sprintf(destfile, "%d.ts", nf);
merge_audio_pic(audio_file, pic_file, destfile);
merged_files.push_back(destfile);
nf++;
if (video.start_time >= audio.end_time - 0.1){//all audio file no video, to next audio
audio_start = audio.end_time + 0.1;//no audio left
return 1;
}
return 0;
}
int MergeProcess::process_video_align_audio()
{
if (audio.end_time > video.end_time){ //this video finish, to next video
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), video.start_time, video.end_time - video.start_time, destfile);
tmp_files.push_back(destfile);
audio_start = video.end_time;
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio, nf, video, destfile);
merged_files.push_back(destfile);
nf++;
}
else if (video.end_time - audio.end_time < 0.1){//just fine, this audio file finish
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), video.start_time, audio.end_time - video.start_time, destfile);
tmp_files.push_back(destfile);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio, nf, video, destfile);
merged_files.push_back(destfile);
audio_start = audio.end_time + 0.1;//no audio left
nf++;
nv++;//this video is used
return 1;
}
else { // this audio finish,add silence and/or next audio
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), video.start_time, audio.end_time - video.start_time, destfile);
vector<std::string > merge_audio_files;
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
audio_start = audio.end_time + 0.1;
double silence_audio_start = audio.end_time;
double silence_audio_end = video.end_time;
bool need_silence = true;
bool to_next_video = false;
for (; audio_index + 1 < filesaudio.size(); audio_index++){//since video is not finished,try find next audio
audio = filesaudio[audio_index + 1];
if (audio.start_time < video.end_time) {//next audio should split to fit the video
silence_audio_end = audio.start_time;
sprintf(destfile, "%d_%d_silence.aac", nf, audio_index);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
if (audio.end_time > video.end_time - 0.1 && audio.end_time < video.end_time + 0.1) {//just match
merge_audio_files.push_back(audio.name);
need_silence = false;
audio_start = audio.end_time + 0.1;
audio_index++;
break;
}
if (audio.end_time > video.end_time){
sprintf(destfile, "%d_%s", nf, audio.name.c_str());
split_audio(audio.name.c_str(), audio_start, audio.end_time - audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
split_audio(audio.name.c_str(), 0, video.end_time - audio.start_time, destfile);
need_silence = false;
//adjust timecode for the audio is part left
float cur_audio_start = video.end_time - audio.start_time;
sprintf(destfile, "%d.ts", nf);
if (nv < filesvideo.size()) {
fileinfo video = filesvideo[nv];
sprintf(pic_file, "%s.jpg", video.name.c_str());
get_video_first_frame_jpeg(video, pic_file);
tmp_files.push_back(pic_file);
audio_start = audio.start_time;
for (int j = audio_index + 1; j < filesaudio.size(); j++){
filesaudio[j].start_time -= audio_start;
filesaudio[j].end_time -= audio_start;
}
else {
strcpy(pic_file, blank_pic_file);
for (int j = nv; j < filesvideo.size(); j++) {
filesvideo[j].start_time -= audio_start;
filesvideo[j].end_time -= audio_start;
}
merge_audio_pic(audio, nf, pic_file, destfile);
merged_files.push_back(destfile);
nf++;
audio_index++;
audio = filesaudio[audio_index];
audio_start = cur_audio_start;
to_next_video = true;
break;
}
merge_audio_files.push_back(audio.name);//whole audio should be appended
silence_audio_start = audio.end_time; //adjust the silence start
audio_start = audio.end_time + 0.1;
}
else {
break;//no need for next audio
}
}
if (need_silence) {
sprintf(destfile, "%d_silence.aac", nf);
split_audio(silence_aac_file, 0, silence_audio_end - silence_audio_start, destfile);
merge_audio_files.push_back(destfile);
tmp_files.push_back(destfile);
}
sprintf(audio_file, "%d_merged.aac", nf);
merge_audio_file(merge_audio_files, audio_file);
sprintf(destfile, "%d.ts", nf);
merge_audio_video(audio_file, video.name.c_str(), destfile);
merged_files.push_back(destfile);
nf++;
if (!to_next_video){
nv++;
return 1;
}
}
return 0;
}
int MergeProcess::process_video_loop()
{
for (; nv < filesvideo.size(); nv++) {
video = filesvideo[nv];
if (video.start_time < audio_start - 0.1)
{//video is much more ahead of audio,try padding silence first
if (process_video_ahead_of_audio())
break;
}//end video is ahead of audio
if (video.start_time - audio_start > 0.1) {//video is behind audio too much
if (process_video_behind_audio())
break;
}
else if (audio_start - video.start_time < 0.1){
if (process_video_align_audio())
break;
}
}
return 0;
}
int MergeProcess::process_va()
{
for (audio_index = 0; audio_index < filesaudio.size(); audio_index++){ //
adjust_va_timestamp();
audio = filesaudio[audio_index];
audio_start = 0;//for a new processing audio,the start is 0
process_video_loop();
merge_left_audio();
}
return 0;
}
int MergeProcess::process_files(const char * output_dest_file)
{
//don't split video, for a video, using merged audios to mix with it
//for audio, mix with video or jpg
if (filesvideo.size()) {//has video files
if (filesaudio.size()){
process_va(); //process the case both audio and video files exist
}
else{//only video
if (filesvideo.size() == 1){
fileinfo video = filesvideo[0];
... ... @@ -772,7 +845,6 @@ int process_files(const char * output_dest_file)
adjust_dest_timecode("m.ts", output_dest_file);
if (!keep_tmp_files) {
removefiles(tmp_files);
removefiles(merged_files);
... ... @@ -866,7 +938,8 @@ int main(int argc, char * argv[])
load_codec_param();
process_files("dest.ts");
MergeProcess mp(media_files[type_audio], media_files[type_video]);
mp.process_files("dest.ts");
return 0;
}
... ...