8 #include "StreamInfo.h"
14 #include "fileavi.inc"
15 #include "mwindow.inc"
22 #define _(String) gettext(String)
23 #define gettext_noop(String) String
24 #define N_(String) gettext_noop (String)
31 int FileAVI::avifile_initialized = 0;
37 // Status of AVI derivatives:
38 // Arne2 - depends on Kino, DV only
39 // Lavtools - 2 gig limited
52 FileAVI::FileAVI(Asset *asset, File *file)
53 : FileBase(asset, file)
63 int FileAVI::check_sig(Asset *asset)
65 // Pick whoever gets the most tracks
66 int score_lavtools = 0;
69 int score_avifile = 0;
77 check_sig_lavtools(asset, score_lavtools);
78 check_sig_arne2(asset, score_arne2);
79 check_sig_arne1(asset, score_arne1);
80 check_sig_avifile(asset, score_avifile);
82 if(score_lavtools > final)
84 final = score_lavtools;
85 result = FILE_AVI_LAVTOOLS;
87 if(score_arne2 > final)
90 result = FILE_AVI_ARNE2;
92 if(score_arne1 > final)
95 result = FILE_AVI_ARNE1;
97 if(score_avifile > final)
99 final = score_avifile;
100 result = FILE_AVI_AVIFILE;
112 int FileAVI::check_sig_arne2(Asset *asset, int &score)
117 int FileAVI::check_sig_arne1(Asset *asset, int &score)
122 int FileAVI::check_sig_lavtools(Asset *asset, int &score)
127 int FileAVI::check_sig_avifile(Asset *asset, int &score)
131 IAviReadFile *in_fd = 0;
135 in_fd = CreateIAviReadFile(asset->path);
137 catch(FatalError& error)
139 if(in_fd) delete in_fd;
143 int vtracks = in_fd->VideoStreamCount();
144 int atracks = in_fd->AudioStreamCount();
148 score = vtracks + atracks;
155 char* FileAVI::vcodec_to_fourcc(char *input, char *output)
158 initialize_avifile();
159 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
160 i < video_codecs.end();
163 if(i->direction & CodecInfo::Encode)
165 if(!strcasecmp(i->GetName(), input))
167 memcpy(output, (char*)&i->fourcc, 4);
181 char* FileAVI::fourcc_to_vcodec(char *input, char *output)
184 // Construct codec item list
185 initialize_avifile();
186 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
187 i < video_codecs.end();
190 if(i->direction & CodecInfo::Encode)
192 if(!memcmp((char*)&i->fourcc, input, 4))
194 memcpy(output, (char*)&i->fourcc, 4);
195 strcpy(output, i->GetName());;
209 char* FileAVI::acodec_to_fourcc(char *input, char *output)
212 // Construct codec item list
213 initialize_avifile();
214 for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
215 i < audio_codecs.end();
218 if(i->direction & CodecInfo::Encode)
220 if(!strcasecmp(i->GetName(), input))
222 memcpy(output, (char*)&i->fourcc, 4);
236 char* FileAVI::fourcc_to_acodec(char *input, char *output)
239 // Construct codec item list
240 initialize_avifile();
241 for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
242 i < audio_codecs.end();
245 if(i->direction & CodecInfo::Encode)
247 if(!memcmp((char*)&i->fourcc, input, 4))
249 memcpy(output, (char*)&i->fourcc, 4);
250 strcpy(output, i->GetName());
264 void FileAVI::initialize_avifile()
267 if(!avifile_initialized)
269 BITMAPINFOHEADER bih;
270 bih.biCompression = 0xffffffff;
271 Creators::CreateVideoDecoder(bih, 0, 0);
274 memset(&wih, 0xff, sizeof(WAVEFORMATEX));
275 Creators::CreateAudioDecoder(&wih, 0);
276 avifile_initialized = 1;
282 int FileAVI::open_file(int rd, int wr)
286 switch(asset->format)
288 case FILE_AVI_LAVTOOLS:
289 return open_lavtools_out(asset);
293 return open_arne2_out(asset);
297 return open_arne1_out(asset);
300 case FILE_AVI_AVIFILE:
301 return open_avifile_out(asset);
308 asset->format = check_sig(asset);
311 switch(asset->format)
313 case FILE_AVI_LAVTOOLS:
314 return open_lavtools_in(asset);
318 return open_arne2_in(asset);
322 return open_arne1_in(asset);
325 case FILE_AVI_AVIFILE:
326 return open_avifile_in(asset);
336 int FileAVI::open_avifile_out(Asset *asset)
341 out_fd = CreateIAviWriteFile(asset->path);
343 catch(FatalError& error)
350 if(asset->video_data)
352 out_color_model = get_best_colormodel(-1, -1);
353 out_bitmap_info = new BitmapInfo(asset->width, asset->height,
354 cmodel_bc_to_avi(out_color_model));
355 for(int i = 0; i < asset->layers && i < MAX_STREAMS; i++)
357 vstream_out[i] = out_fd->AddVideoStream(*(uint32_t*)asset->vcodec,
359 int(1000000.0 / asset->frame_rate));
363 if(asset->audio_data)
366 wfm.wFormatTag = 1; // PCM
367 wfm.nChannels = asset->channels;
368 wfm.nSamplesPerSec = asset->sample_rate;
369 wfm.nAvgBytesPerSec = 2 * asset->sample_rate * asset->channels;
370 wfm.nBlockAlign = 2 * asset->channels;
371 wfm.wBitsPerSample = 16;
374 for(int i = 0; i < asset->channels && i < MAX_STREAMS; i++)
376 astream_out[i] = out_fd->AddStream(AviStream::Audio,
379 1, // uncompressed PCM data
380 wfm.nAvgBytesPerSec, // bytes/sec
381 wfm.nBlockAlign); // bytes/sample
390 int FileAVI::open_arne2_out(Asset *asset)
396 int FileAVI::open_arne1_out(Asset *asset)
401 int FileAVI::open_lavtools_out(Asset *asset)
411 int FileAVI::open_avifile_in(Asset *asset)
416 in_fd = CreateIAviReadFile(asset->path);
418 catch(FatalError& error)
425 asset->layers = in_fd->VideoStreamCount();
428 for(int i = 0; i < asset->layers && i < MAX_STREAMS; i++)
430 vstream_in[i] = in_fd->GetStream(i, IAviReadStream::Video);
431 vstream_in[i]->StartStreaming();
432 vstream_in[i]->GetDecoder()->SetDestFmt(24);
433 vstream_in[i]->Seek(0);
434 //printf("FileAVI::open_file %d %p\n", i, vstream[i]);
437 StreamInfo *stream_info = vstream_in[0]->GetStreamInfo();
438 asset->video_data = 1;
439 if(!asset->frame_rate)
440 asset->frame_rate = (double)1 / vstream_in[0]->GetFrameTime();
441 asset->video_length = stream_info->GetStreamFrames();
443 vstream_in[0]->GetVideoFormatInfo(&bh, sizeof(bh));
444 asset->width = bh.biWidth;
445 asset->height = bh.biHeight;
447 uint32_t fourcc = stream_info->GetFormat();
448 asset->vcodec[0] = ((char*)&fourcc)[0];
449 asset->vcodec[1] = ((char*)&fourcc)[1];
450 asset->vcodec[2] = ((char*)&fourcc)[2];
451 asset->vcodec[3] = ((char*)&fourcc)[3];
452 source_cmodel = BC_RGB888;
456 asset->audio_data = in_fd->AudioStreamCount();
458 if(asset->audio_data)
462 for(int i = 0; i < 1 && i < MAX_STREAMS; i++)
464 astream_in[i] = in_fd->GetStream(i, IAviReadStream::Audio);
465 astream_in[i]->StartStreaming();
468 StreamInfo *stream_info = astream_in[0]->GetStreamInfo();
469 asset->channels = stream_info->GetAudioChannels();
470 if(asset->sample_rate == 0)
471 asset->sample_rate = stream_info->GetAudioSamplesPerSec();
472 asset->bits = MAX(16, stream_info->GetAudioBitsPerSample());
473 asset->audio_length = stream_info->GetStreamFrames();
482 int FileAVI::open_arne2_in(Asset *asset)
487 int FileAVI::open_arne1_in(Asset *asset)
492 int FileAVI::open_lavtools_in(Asset *asset)
514 int FileAVI::close_file()
517 if(in_fd) delete in_fd;
518 if(out_fd) delete out_fd;
519 if(out_bitmap_info) delete out_bitmap_info;
521 if(temp_audio) delete [] temp_audio;
525 int FileAVI::cmodel_bc_to_avi(int input)
542 void FileAVI::reset()
553 int FileAVI::get_best_colormodel(int driver, int colormodel)
567 void FileAVI::get_parameters(BC_WindowBase *parent_window,
569 BC_WindowBase* &format_window,
576 AVIConfigAudio *window = new AVIConfigAudio(parent_window, asset);
577 format_window = window;
578 window->create_objects();
579 window->run_window();
585 //printf("FileAVI::get_parameters 1\n");
586 AVIConfigVideo *window = new AVIConfigVideo(parent_window,
589 format_window = window;
590 window->create_objects();
591 window->run_window();
596 int FileAVI::set_audio_position(int64_t x)
599 // quicktime sets positions for each track seperately so store position in audio_position
600 if(x >= 0 && x < asset->audio_length)
601 return astream_in[file->current_layer]->Seek(x);
607 int FileAVI::set_video_position(int64_t x)
610 if(x >= 0 && x < asset->video_length)
611 return vstream_in[file->current_layer]->Seek(x);
617 int FileAVI::read_samples(double *buffer, int64_t len)
620 Unsigned samples_read, bytes_read;
622 printf("FileAVI::read_samples 1\n");
623 if(temp_audio && temp_allocated < len * asset->bits / 8 * asset->channels)
625 delete [] temp_audio;
630 temp_allocated = len * asset->bits / 8 * asset->channels;
631 temp_audio = new unsigned char[temp_allocated];
634 astream_in[0]->ReadFrames((void*)temp_audio,
635 (unsigned int)temp_allocated,
640 // Extract single channel
645 int16_t *temp_int16 = (int16_t*)temp_audio;
646 for(int i = 0, j = file->current_channel;
648 i++, j += asset->channels)
650 buffer[i] = (double)temp_int16[j] / 32767;
662 int FileAVI::read_frame(VFrame *frame)
667 vstream_in[file->current_layer]->ReadFrame();
668 CImage *temp_image = vstream_in[file->current_layer]->GetFrame();
669 //printf("FileAVI::read_frame 1 %d %d\n", source_cmodel, frame->get_color_model());
670 switch(source_cmodel)
673 if(frame->get_color_model() == BC_RGB888)
674 bcopy(temp_image->Data(),
676 VFrame::calculate_data_size(asset->width,
686 int64_t FileAVI::compressed_frame_size()
692 int FileAVI::read_compressed_frame(VFrame *buffer)
699 int FileAVI::write_compressed_frame(VFrame *buffer)
706 int FileAVI::write_frames(VFrame ***frames, int len)
712 int FileAVI::write_samples(double **buffer, int64_t len)
721 AVIConfigAudio::AVIConfigAudio(BC_WindowBase *parent_window, Asset *asset)
722 : BC_Window(PROGRAM_NAME ": Audio compression",
723 parent_window->get_abs_cursor_x(),
724 parent_window->get_abs_cursor_y(),
725 calculate_w(asset->format),
726 calculate_h(asset->format))
728 this->parent_window = parent_window;
732 AVIConfigAudio::~AVIConfigAudio()
736 int AVIConfigAudio::calculate_w(int format)
740 case FILE_AVI_AVIFILE: return 400; break;
741 case FILE_AVI_ARNE2: return 250; break;
745 int AVIConfigAudio::calculate_h(int format)
749 case FILE_AVI_AVIFILE: return 200; break;
750 case FILE_AVI_ARNE2: return 100; break;
754 int AVIConfigAudio::create_objects()
756 switch(asset->format)
759 case FILE_AVI_AVIFILE:
761 generate_codeclist();
765 add_subwindow(title = new BC_Title(x, y, _("Codec: ")));
766 list = new AVIACodecList(this, x, y);
767 list->create_objects();
774 add_subwindow(new BC_Title(10, 10, _("Compressor: 16 bit PCM")));
778 add_subwindow(new BC_OKButton(this));
782 int AVIConfigAudio::close_event()
787 int AVIConfigAudio::generate_codeclist()
789 FileAVI::initialize_avifile();
790 codec_items.remove_all_objects();
792 switch(asset->format)
795 case FILE_AVI_AVIFILE:
796 for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
797 i < audio_codecs.end();
800 if(i->direction & CodecInfo::Encode)
802 codec_items.append(new BC_ListBoxItem((char*)i->GetName()));
812 void AVIConfigAudio::update_codecs()
825 AVIACodecList::AVIACodecList(AVIConfigAudio *gui, int x, int y)
826 : BC_PopupTextBox(gui,
828 FileAVI::fourcc_to_acodec(gui->asset->acodec, gui->string),
837 AVIACodecList::~AVIACodecList()
841 int AVIACodecList::handle_event()
843 strcpy(gui->asset->acodec, FileAVI::acodec_to_fourcc(get_text(), gui->string));
851 AVIConfigVideo::AVIConfigVideo(BC_WindowBase *parent_window,
854 : BC_Window(PROGRAM_NAME ": Video Compression",
855 parent_window->get_abs_cursor_x(),
856 parent_window->get_abs_cursor_y(),
857 calculate_w(asset->format),
858 calculate_h(asset->format))
860 this->parent_window = parent_window;
862 this->lock_compressor = lock_compressor;
866 AVIConfigVideo::~AVIConfigVideo()
868 codec_items.remove_all_objects();
869 attribute_items[0].remove_all_objects();
870 attribute_items[1].remove_all_objects();
873 void AVIConfigVideo::reset()
879 int AVIConfigVideo::calculate_w(int format)
883 case FILE_AVI_AVIFILE: return 400; break;
884 case FILE_AVI_ARNE2: return 250; break;
888 int AVIConfigVideo::calculate_h(int format)
892 case FILE_AVI_AVIFILE: return 320; break;
893 case FILE_AVI_ARNE2: return 100; break;
897 int AVIConfigVideo::create_objects()
899 switch(asset->format)
902 case FILE_AVI_AVIFILE:
904 generate_codeclist();
905 generate_attributelist();
907 int x = 10, y = 10, x1 = 90;
909 add_subwindow(title = new BC_Title(x, y, _("Codec: ")));
910 list = new AVIVCodecList(this, x1, y);
911 list->create_objects();
912 y += list->get_h() + 5;
914 add_subwindow(title = new BC_Title(x, y, _("Attributes:")));
915 add_subwindow(attributes = new AVIVAttributeList(this, x1, y));
916 y += attributes->get_h() + 5;
918 add_subwindow(new BC_Title(x, y, _("Value:")));
919 add_subwindow(attribute = new AVIVAttribute(this, x1, y));
925 add_subwindow(new BC_Title(10, 10, _("Compressor: Consumer DV")));
929 add_subwindow(new BC_OKButton(this));
933 int AVIConfigVideo::close_event()
938 int AVIConfigVideo::generate_codeclist()
940 FileAVI::initialize_avifile();
941 switch(asset->format)
943 case FILE_AVI_AVIFILE:
945 // Construct codec item list
946 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
947 i < video_codecs.end();
950 if(i->direction & CodecInfo::Encode)
952 codec_items.append(new BC_ListBoxItem((char*)i->GetName()));
962 void AVIConfigVideo::generate_attributelist()
965 // Remember selection number
966 int selection_number = attributes ? attributes->get_selection_number(0, 0) : -1;
967 attribute_items[0].remove_all_objects();
968 attribute_items[1].remove_all_objects();
969 FileAVI::initialize_avifile();
971 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
972 i < video_codecs.end();
975 if(!memcmp((char*)&i->fourcc, asset->vcodec, 4))
977 avm::vector<AttributeInfo>& attributes = i->encoder_info;
979 for(avm::vector<AttributeInfo>::const_iterator j = attributes.begin();
980 j < attributes.end();
983 char *name = (char*)j->GetName();
984 char value[BCTEXTLEN];
987 //printf("AVIConfigVideo::generate_attributelist %d\n", j->kind);
990 case AttributeInfo::Integer:
993 Creators::GetCodecAttr(*i, name, temp);
994 sprintf(value, "%d", temp);
998 case AttributeInfo::Select:
1001 Creators::GetCodecAttr(*i, name, temp);
1002 sprintf(value, "%d ( %s )", temp, j->options[temp].c_str());
1006 case AttributeInfo::String:
1007 Creators::GetCodecAttr(*i, name, value, BCTEXTLEN);
1011 attribute_items[0].append(new BC_ListBoxItem(name));
1012 attribute_items[1].append(new BC_ListBoxItem(value));
1014 int current_number = j - attributes.begin();
1015 if(current_number == selection_number)
1017 attribute_items[0].values[current_number]->set_selected(1);
1018 attribute_items[1].values[current_number]->set_selected(1);
1026 char* AVIConfigVideo::get_current_attribute_text()
1028 BC_ListBoxItem *item = attributes->get_selection(0, 0);
1032 return item->get_text();
1038 char* AVIConfigVideo::get_current_attribute_value()
1040 BC_ListBoxItem *item = attributes->get_selection(1, 0);
1044 return item->get_text();
1050 void AVIConfigVideo::set_current_attribute(char *text)
1053 int number = attributes->get_selection_number(0, 0);
1057 FileAVI::initialize_avifile();
1059 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
1060 i < video_codecs.end();
1063 if(!memcmp((char*)&i->fourcc, asset->vcodec, 4))
1065 avm::vector<AttributeInfo>& attributes = i->encoder_info;
1066 AttributeInfo& attribute = attributes[number];
1068 switch(attribute.kind)
1070 case AttributeInfo::Integer:
1071 Creators::SetCodecAttr(*i, attribute.GetName(), atol(text));
1074 case AttributeInfo::Select:
1075 Creators::SetCodecAttr(*i, attribute.GetName(), atol(text));
1078 case AttributeInfo::String:
1079 Creators::SetCodecAttr(*i, attribute.GetName(), text);
1086 update_attribute(1);
1093 void AVIConfigVideo::update_attribute(int recursive)
1095 generate_attributelist();
1096 attributes->update(attribute_items,
1100 attributes->get_xposition(),
1101 attributes->get_yposition(),
1105 if(!recursive) attribute->update(get_current_attribute_value());
1116 AVIVCodecList::AVIVCodecList(AVIConfigVideo *gui, int x, int y)
1117 : BC_PopupTextBox(gui,
1119 FileAVI::fourcc_to_vcodec(gui->asset->vcodec, gui->string),
1128 AVIVCodecList::~AVIVCodecList()
1132 int AVIVCodecList::handle_event()
1134 strcpy(gui->asset->vcodec, FileAVI::vcodec_to_fourcc(get_text(), gui->string));
1135 gui->update_attribute(0);
1141 AVIVAttributeList::AVIVAttributeList(AVIConfigVideo *gui, int x, int y)
1147 gui->attribute_items,
1155 int AVIVAttributeList::handle_event()
1157 gui->update_attribute(0);
1161 int AVIVAttributeList::selection_changed()
1163 gui->update_attribute(0);
1170 AVIVAttribute::AVIVAttribute(AVIConfigVideo *gui, int x, int y)
1171 : BC_TextBox(x, y, 300, 1, gui->get_current_attribute_value())
1176 int AVIVAttribute::handle_event()
1178 gui->set_current_attribute(get_text());