7 #include "avm_fourcc.h"
8 #include "StreamInfo.h"
14 #include "fileavi.inc"
15 #include "interlacemodes.h"
16 #include "mwindow.inc"
23 #define _(String) gettext(String)
24 #define gettext_noop(String) String
25 #define N_(String) gettext_noop (String)
32 int FileAVI::avifile_initialized = 0;
38 // Status of AVI derivatives:
39 // Arne2 - depends on Kino, DV only
40 // Lavtools - 2 gig limited
53 FileAVI::FileAVI(Asset *asset, File *file)
54 : FileBase(asset, file)
64 int FileAVI::check_sig(Asset *asset)
66 // Pick whoever gets the most tracks
67 int score_lavtools = 0;
70 int score_avifile = 0;
78 check_sig_lavtools(asset, score_lavtools);
79 check_sig_arne2(asset, score_arne2);
80 check_sig_arne1(asset, score_arne1);
81 check_sig_avifile(asset, score_avifile);
83 if(score_lavtools > final)
85 final = score_lavtools;
86 result = FILE_AVI_LAVTOOLS;
88 if(score_arne2 > final)
91 result = FILE_AVI_ARNE2;
93 if(score_arne1 > final)
96 result = FILE_AVI_ARNE1;
98 if(score_avifile > final)
100 final = score_avifile;
101 result = FILE_AVI_AVIFILE;
113 int FileAVI::check_sig_arne2(Asset *asset, int &score)
118 int FileAVI::check_sig_arne1(Asset *asset, int &score)
123 int FileAVI::check_sig_lavtools(Asset *asset, int &score)
128 int FileAVI::check_sig_avifile(Asset *asset, int &score)
132 IAviReadFile *in_fd = 0;
136 in_fd = CreateIAviReadFile(asset->path);
138 catch(FatalError& error)
140 if(in_fd) delete in_fd;
144 int vtracks = in_fd->VideoStreamCount();
145 int atracks = in_fd->AudioStreamCount();
149 score = vtracks + atracks;
156 char* FileAVI::vcodec_to_fourcc(char *input, char *output)
159 initialize_avifile();
160 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
161 i < video_codecs.end();
164 if(i->direction & CodecInfo::Encode)
166 if(!strcasecmp(i->GetName(), input))
168 memcpy(output, (char*)&i->fourcc, 4);
182 char* FileAVI::fourcc_to_vcodec(char *input, char *output)
185 // Construct codec item list
186 initialize_avifile();
187 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
188 i < video_codecs.end();
191 if(i->direction & CodecInfo::Encode)
193 if(!memcmp((char*)&i->fourcc, input, 4))
195 memcpy(output, (char*)&i->fourcc, 4);
196 strcpy(output, i->GetName());;
210 char* FileAVI::acodec_to_fourcc(char *input, char *output)
213 // Construct codec item list
214 initialize_avifile();
215 for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
216 i < audio_codecs.end();
219 if(i->direction & CodecInfo::Encode)
221 if(!strcasecmp(i->GetName(), input))
223 memcpy(output, (char*)&i->fourcc, 4);
237 char* FileAVI::fourcc_to_acodec(char *input, char *output)
240 // Construct codec item list
241 initialize_avifile();
242 for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
243 i < audio_codecs.end();
246 if(i->direction & CodecInfo::Encode)
248 if(!memcmp((char*)&i->fourcc, input, 4))
250 memcpy(output, (char*)&i->fourcc, 4);
251 strcpy(output, i->GetName());
265 void FileAVI::initialize_avifile()
268 if(!avifile_initialized)
270 BITMAPINFOHEADER bih;
271 bih.biCompression = 0xffffffff;
272 Creators::CreateVideoDecoder(bih, 0, 0);
275 memset(&wih, 0xff, sizeof(WAVEFORMATEX));
276 Creators::CreateAudioDecoder(&wih, 0);
277 avifile_initialized = 1;
283 int FileAVI::open_file(int rd, int wr)
287 switch(asset->format)
289 case FILE_AVI_LAVTOOLS:
290 return open_lavtools_out(asset);
294 return open_arne2_out(asset);
298 return open_arne1_out(asset);
301 case FILE_AVI_AVIFILE:
302 return open_avifile_out(asset);
309 asset->format = check_sig(asset);
312 switch(asset->format)
314 case FILE_AVI_LAVTOOLS:
315 return open_lavtools_in(asset);
319 return open_arne2_in(asset);
323 return open_arne1_in(asset);
326 case FILE_AVI_AVIFILE:
327 return open_avifile_in(asset);
337 int FileAVI::open_avifile_out(Asset *asset)
342 out_fd = CreateIAviWriteFile(asset->path);
344 catch(FatalError& error)
351 if(asset->video_data)
353 out_color_model = get_best_colormodel(-1, -1);
354 out_bitmap_info = new BitmapInfo(asset->width, asset->height,
355 cmodel_bc_to_avi(out_color_model));
356 for(int i = 0; i < asset->layers && i < MAX_STREAMS; i++)
358 vstream_out[i] = out_fd->AddVideoStream(*(uint32_t*)asset->vcodec,
360 int(1000000.0 / asset->frame_rate));
364 if(asset->audio_data)
367 wfm.wFormatTag = 1; // PCM
368 wfm.nChannels = asset->channels;
369 wfm.nSamplesPerSec = asset->sample_rate;
370 wfm.nAvgBytesPerSec = 2 * asset->sample_rate * asset->channels;
371 wfm.nBlockAlign = 2 * asset->channels;
372 wfm.wBitsPerSample = 16;
375 for(int i = 0; i < asset->channels && i < MAX_STREAMS; i++)
377 astream_out[i] = out_fd->AddStream(AviStream::Audio,
380 1, // uncompressed PCM data
381 wfm.nAvgBytesPerSec, // bytes/sec
382 wfm.nBlockAlign); // bytes/sample
391 int FileAVI::open_arne2_out(Asset *asset)
397 int FileAVI::open_arne1_out(Asset *asset)
402 int FileAVI::open_lavtools_out(Asset *asset)
412 int FileAVI::open_avifile_in(Asset *asset)
417 in_fd = CreateIAviReadFile(asset->path);
419 catch(FatalError& error)
426 asset->layers = in_fd->VideoStreamCount();
429 for(int i = 0; i < asset->layers && i < MAX_STREAMS; i++)
431 vstream_in[i] = in_fd->GetStream(i, IAviReadStream::Video);
432 vstream_in[i]->StartStreaming();
433 vstream_in[i]->GetDecoder()->SetDestFmt(24);
434 vstream_in[i]->Seek(0);
435 //printf("FileAVI::open_file %d %p\n", i, vstream[i]);
438 StreamInfo *stream_info = vstream_in[0]->GetStreamInfo();
439 asset->video_data = 1;
440 if(!asset->frame_rate)
441 asset->frame_rate = (double)1 / vstream_in[0]->GetFrameTime();
442 asset->video_length = stream_info->GetStreamFrames();
444 vstream_in[0]->GetVideoFormatInfo(&bh, sizeof(bh));
445 asset->width = bh.biWidth;
446 asset->height = bh.biHeight;
447 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED; // FIXME
449 uint32_t fourcc = stream_info->GetFormat();
450 asset->vcodec[0] = ((char*)&fourcc)[0];
451 asset->vcodec[1] = ((char*)&fourcc)[1];
452 asset->vcodec[2] = ((char*)&fourcc)[2];
453 asset->vcodec[3] = ((char*)&fourcc)[3];
454 source_cmodel = BC_RGB888;
458 asset->audio_data = in_fd->AudioStreamCount();
460 if(asset->audio_data)
464 for(int i = 0; i < 1 && i < MAX_STREAMS; i++)
466 astream_in[i] = in_fd->GetStream(i, IAviReadStream::Audio);
467 astream_in[i]->StartStreaming();
470 StreamInfo *stream_info = astream_in[0]->GetStreamInfo();
471 asset->channels = stream_info->GetAudioChannels();
472 if(asset->sample_rate == 0)
473 asset->sample_rate = stream_info->GetAudioSamplesPerSec();
474 asset->bits = MAX(16, stream_info->GetAudioBitsPerSample());
475 asset->audio_length = stream_info->GetStreamFrames();
484 int FileAVI::open_arne2_in(Asset *asset)
489 int FileAVI::open_arne1_in(Asset *asset)
494 int FileAVI::open_lavtools_in(Asset *asset)
516 int FileAVI::close_file()
519 if(in_fd) delete in_fd;
520 if(out_fd) delete out_fd;
521 if(out_bitmap_info) delete out_bitmap_info;
523 if(temp_audio) delete [] temp_audio;
527 int FileAVI::cmodel_bc_to_avi(int input)
544 void FileAVI::reset()
555 int FileAVI::get_best_colormodel(int driver, int colormodel)
569 void FileAVI::get_parameters(BC_WindowBase *parent_window,
571 BC_WindowBase* &format_window,
574 char *locked_compressor)
578 AVIConfigAudio *window = new AVIConfigAudio(parent_window, asset);
579 format_window = window;
580 window->create_objects();
581 window->run_window();
587 //printf("FileAVI::get_parameters 1\n");
588 AVIConfigVideo *window = new AVIConfigVideo(parent_window,
591 format_window = window;
592 window->create_objects();
593 window->run_window();
598 int FileAVI::set_audio_position(int64_t x)
601 // quicktime sets positions for each track seperately so store position in audio_position
602 if(x >= 0 && x < asset->audio_length)
603 return astream_in[file->current_layer]->Seek(x);
609 int FileAVI::set_video_position(int64_t x)
612 if(x >= 0 && x < asset->video_length)
613 return vstream_in[file->current_layer]->Seek(x);
619 int FileAVI::read_samples(double *buffer, int64_t len)
622 Unsigned samples_read, bytes_read;
624 printf("FileAVI::read_samples 1\n");
625 if(temp_audio && temp_allocated < len * asset->bits / 8 * asset->channels)
627 delete [] temp_audio;
632 temp_allocated = len * asset->bits / 8 * asset->channels;
633 temp_audio = new unsigned char[temp_allocated];
636 astream_in[0]->ReadFrames((void*)temp_audio,
637 (unsigned int)temp_allocated,
642 // Extract single channel
647 int16_t *temp_int16 = (int16_t*)temp_audio;
648 for(int i = 0, j = file->current_channel;
650 i++, j += asset->channels)
652 buffer[i] = (double)temp_int16[j] / 32767;
664 int FileAVI::read_frame(VFrame *frame)
669 vstream_in[file->current_layer]->ReadFrame();
670 CImage *temp_image = vstream_in[file->current_layer]->GetFrame();
671 //printf("FileAVI::read_frame 1 %d %d\n", source_cmodel, frame->get_color_model());
672 switch(source_cmodel)
675 if(frame->get_color_model() == BC_RGB888)
676 bcopy(temp_image->Data(),
678 VFrame::calculate_data_size(asset->width,
688 int64_t FileAVI::compressed_frame_size()
694 int FileAVI::read_compressed_frame(VFrame *buffer)
701 int FileAVI::write_compressed_frame(VFrame *buffer)
708 int FileAVI::write_frames(VFrame ***frames, int len)
714 int FileAVI::write_samples(double **buffer, int64_t len)
723 AVIConfigAudio::AVIConfigAudio(BC_WindowBase *parent_window, Asset *asset)
724 : BC_Window(PROGRAM_NAME ": Audio compression",
725 parent_window->get_abs_cursor_x(1),
726 parent_window->get_abs_cursor_y(1),
727 calculate_w(asset->format),
728 calculate_h(asset->format))
730 this->parent_window = parent_window;
734 AVIConfigAudio::~AVIConfigAudio()
738 int AVIConfigAudio::calculate_w(int format)
742 case FILE_AVI_AVIFILE: return 400; break;
743 case FILE_AVI_ARNE2: return 250; break;
747 int AVIConfigAudio::calculate_h(int format)
751 case FILE_AVI_AVIFILE: return 200; break;
752 case FILE_AVI_ARNE2: return 100; break;
756 int AVIConfigAudio::create_objects()
758 switch(asset->format)
761 case FILE_AVI_AVIFILE:
763 generate_codeclist();
767 add_subwindow(title = new BC_Title(x, y, _("Codec: ")));
768 list = new AVIACodecList(this, x, y);
769 list->create_objects();
776 add_subwindow(new BC_Title(10, 10, _("Compressor: 16 bit PCM")));
780 add_subwindow(new BC_OKButton(this));
784 int AVIConfigAudio::close_event()
789 int AVIConfigAudio::generate_codeclist()
791 FileAVI::initialize_avifile();
792 codec_items.remove_all_objects();
794 switch(asset->format)
797 case FILE_AVI_AVIFILE:
798 for(avm::vector<CodecInfo>::iterator i = audio_codecs.begin();
799 i < audio_codecs.end();
802 if(i->direction & CodecInfo::Encode)
804 codec_items.append(new BC_ListBoxItem((char*)i->GetName()));
814 void AVIConfigAudio::update_codecs()
827 AVIACodecList::AVIACodecList(AVIConfigAudio *gui, int x, int y)
828 : BC_PopupTextBox(gui,
830 FileAVI::fourcc_to_acodec(gui->asset->acodec, gui->string),
839 AVIACodecList::~AVIACodecList()
843 int AVIACodecList::handle_event()
845 strcpy(gui->asset->acodec, FileAVI::acodec_to_fourcc(get_text(), gui->string));
853 AVIConfigVideo::AVIConfigVideo(BC_WindowBase *parent_window,
855 char *locked_compressor)
856 : BC_Window(PROGRAM_NAME ": Video Compression",
857 parent_window->get_abs_cursor_x(1),
858 parent_window->get_abs_cursor_y(1),
859 calculate_w(asset->format),
860 calculate_h(asset->format))
862 this->parent_window = parent_window;
864 this->locked_compressor = locked_compressor;
868 AVIConfigVideo::~AVIConfigVideo()
870 codec_items.remove_all_objects();
871 attribute_items[0].remove_all_objects();
872 attribute_items[1].remove_all_objects();
875 void AVIConfigVideo::reset()
881 int AVIConfigVideo::calculate_w(int format)
885 case FILE_AVI_AVIFILE: return 400; break;
886 case FILE_AVI_ARNE2: return 250; break;
890 int AVIConfigVideo::calculate_h(int format)
894 case FILE_AVI_AVIFILE: return 320; break;
895 case FILE_AVI_ARNE2: return 100; break;
899 int AVIConfigVideo::create_objects()
901 switch(asset->format)
904 case FILE_AVI_AVIFILE:
906 generate_codeclist();
907 generate_attributelist();
909 int x = 10, y = 10, x1 = 90;
911 add_subwindow(title = new BC_Title(x, y, _("Codec: ")));
912 list = new AVIVCodecList(this, x1, y);
913 list->create_objects();
914 y += list->get_h() + 5;
916 add_subwindow(title = new BC_Title(x, y, _("Attributes:")));
917 add_subwindow(attributes = new AVIVAttributeList(this, x1, y));
918 y += attributes->get_h() + 5;
920 add_subwindow(new BC_Title(x, y, _("Value:")));
921 add_subwindow(attribute = new AVIVAttribute(this, x1, y));
927 add_subwindow(new BC_Title(10, 10, _("Compressor: Consumer DV")));
931 add_subwindow(new BC_OKButton(this));
935 int AVIConfigVideo::close_event()
940 int AVIConfigVideo::generate_codeclist()
942 FileAVI::initialize_avifile();
943 switch(asset->format)
945 case FILE_AVI_AVIFILE:
947 // Construct codec item list
948 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
949 i < video_codecs.end();
952 if(i->direction & CodecInfo::Encode)
954 codec_items.append(new BC_ListBoxItem((char*)i->GetName()));
964 void AVIConfigVideo::generate_attributelist()
967 // Remember selection number
968 int selection_number = attributes ? attributes->get_selection_number(0, 0) : -1;
969 attribute_items[0].remove_all_objects();
970 attribute_items[1].remove_all_objects();
971 FileAVI::initialize_avifile();
973 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
974 i < video_codecs.end();
977 if(!memcmp((char*)&i->fourcc, asset->vcodec, 4))
979 avm::vector<AttributeInfo>& attributes = i->encoder_info;
981 for(avm::vector<AttributeInfo>::const_iterator j = attributes.begin();
982 j != attributes.end();
985 char *name = (char*)j->GetName();
986 char value[BCTEXTLEN];
989 //printf("AVIConfigVideo::generate_attributelist %d\n", j->kind);
992 case AttributeInfo::Integer:
995 Creators::GetCodecAttr(*i, name, temp);
996 sprintf(value, "%d", temp);
1000 case AttributeInfo::Select:
1003 Creators::GetCodecAttr(*i, name, temp);
1004 sprintf(value, "%d ( %s )", temp, j->options[temp].c_str());
1008 case AttributeInfo::String:
1010 const char * temp = 0;
1011 Creators::GetCodecAttr(*i, name, &temp);
1012 if(temp) strncpy(value, temp, BCTEXTLEN);
1017 attribute_items[0].append(new BC_ListBoxItem(name));
1018 attribute_items[1].append(new BC_ListBoxItem(value));
1020 int current_number = j - attributes.begin();
1021 if(current_number == selection_number)
1023 attribute_items[0].values[current_number]->set_selected(1);
1024 attribute_items[1].values[current_number]->set_selected(1);
1032 char* AVIConfigVideo::get_current_attribute_text()
1034 BC_ListBoxItem *item = attributes->get_selection(0, 0);
1038 return item->get_text();
1044 char* AVIConfigVideo::get_current_attribute_value()
1046 BC_ListBoxItem *item = attributes->get_selection(1, 0);
1050 return item->get_text();
1056 void AVIConfigVideo::set_current_attribute(char *text)
1059 int number = attributes->get_selection_number(0, 0);
1063 FileAVI::initialize_avifile();
1065 for(avm::vector<CodecInfo>::iterator i = video_codecs.begin();
1066 i < video_codecs.end();
1069 if(!memcmp((char*)&i->fourcc, asset->vcodec, 4))
1071 avm::vector<AttributeInfo>& attributes = i->encoder_info;
1072 AttributeInfo& attribute = attributes[number];
1074 switch(attribute.kind)
1076 case AttributeInfo::Integer:
1077 Creators::SetCodecAttr(*i, attribute.GetName(), atol(text));
1080 case AttributeInfo::Select:
1081 Creators::SetCodecAttr(*i, attribute.GetName(), atol(text));
1084 case AttributeInfo::String:
1085 Creators::SetCodecAttr(*i, attribute.GetName(), text);
1092 update_attribute(1);
1099 void AVIConfigVideo::update_attribute(int recursive)
1101 generate_attributelist();
1102 attributes->update(attribute_items,
1106 attributes->get_xposition(),
1107 attributes->get_yposition(),
1111 if(!recursive) attribute->update(get_current_attribute_value());
1122 AVIVCodecList::AVIVCodecList(AVIConfigVideo *gui, int x, int y)
1123 : BC_PopupTextBox(gui,
1125 FileAVI::fourcc_to_vcodec(gui->asset->vcodec, gui->string),
1134 AVIVCodecList::~AVIVCodecList()
1138 int AVIVCodecList::handle_event()
1140 strcpy(gui->asset->vcodec, FileAVI::vcodec_to_fourcc(get_text(), gui->string));
1141 gui->update_attribute(0);
1147 AVIVAttributeList::AVIVAttributeList(AVIConfigVideo *gui, int x, int y)
1153 gui->attribute_items,
1161 int AVIVAttributeList::handle_event()
1163 gui->update_attribute(0);
1167 int AVIVAttributeList::selection_changed()
1169 gui->update_attribute(0);
1176 AVIVAttribute::AVIVAttribute(AVIConfigVideo *gui, int x, int y)
1177 : BC_TextBox(x, y, 300, 1, gui->get_current_attribute_value())
1182 int AVIVAttribute::handle_event()
1184 gui->set_current_attribute(get_text());