00001 #include "asset.h"
00002 #include "bcsignals.h"
00003 #include "bitspopup.h"
00004 #include "byteorder.h"
00005 #include "condition.h"
00006 #include "edit.h"
00007 #include "file.h"
00008 #include "filemov.h"
00009 #include "guicast.h"
00010 #include "language.h"
00011 #include "mwindow.inc"
00012 #include "vframe.h"
00013 #include "videodevice.inc"
00014
00015 #include <unistd.h>
00016 #include <libdv/dv.h>
00017
00018 #if 0
00019 N_("MPEG-4")
00020 N_("Dual H.264")
00021 N_("Dual MPEG-4")
00022 N_("H.264")
00023 N_("H.263")
00024 N_("Microsoft MPEG-4")
00025 N_("DV")
00026 N_("PNG")
00027 N_("PNG with Alpha")
00028 N_("Uncompressed RGB")
00029 N_("Uncompressed RGBA")
00030 N_("YUV 4:2:0 Planar")
00031 N_("Component Video")
00032 N_("YUV 4:1:1 Packed")
00033 N_("Component Y'CbCr 8-bit 4:4:4")
00034 N_("Component Y'CbCrA 8-bit 4:4:4:4")
00035 N_("Component Y'CbCr 10-bit 4:4:4")
00036 N_("JPEG Photo")
00037 N_("Motion JPEG A")
00038
00039
00040 N_("Twos complement")
00041 N_("Unsigned")
00042 N_("IMA-4")
00043 N_("U-Law")
00044 N_("Vorbis")
00045 N_("MP3")
00046 N_("MPEG-4 Audio")
00047 #endif
00048
00049 #define DIVX_NAME "MPEG-4"
00050 #define HV64_NAME "Dual H.264"
00051 #define MP4V_NAME "MPEG-4 Video"
00052 #define H264_NAME "H.264"
00053 #define H263_NAME "H.263"
00054 #define HV60_NAME "Dual MPEG-4"
00055 #define DIV3_NAME "Microsoft MPEG-4"
00056 #define DV_NAME "DV"
00057 #define PNG_NAME "PNG"
00058 #define PNGA_NAME "PNG with Alpha"
00059 #define RGB_NAME "Uncompressed RGB"
00060 #define RGBA_NAME "Uncompressed RGBA"
00061 #define YUV420_NAME "YUV 4:2:0 Planar"
00062 #define YUV422_NAME "Component Video"
00063 #define YUV411_NAME "YUV 4:1:1 Packed"
00064 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
00065 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
00066 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
00067 #define QTJPEG_NAME "JPEG Photo"
00068 #define MJPA_NAME "Motion JPEG A"
00069
00070 #define TWOS_NAME "Twos complement"
00071 #define RAW_NAME "Unsigned"
00072 #define IMA4_NAME "IMA-4"
00073 #define ULAW_NAME "U-Law"
00074
00075 #define MP3_NAME "MP3"
00076 #define MP4A_NAME "MPEG-4 Audio"
00077 #define VORBIS_NAME "OGG Vorbis"
00078
00079
00080
00081
00082
00083 FileMOV::FileMOV(Asset *asset, File *file)
00084 : FileBase(asset, file)
00085 {
00086 reset_parameters();
00087 if(asset->format == FILE_UNKNOWN)
00088 asset->format = FILE_MOV;
00089 asset->byte_order = 0;
00090 suffix_number = 0;
00091 threadframe_lock = new Mutex("FileMOV::threadframe_lock");
00092 }
00093
00094 FileMOV::~FileMOV()
00095 {
00096 close_file();
00097 delete threadframe_lock;
00098 }
00099
00100 void FileMOV::get_parameters(BC_WindowBase *parent_window,
00101 Asset *asset,
00102 BC_WindowBase* &format_window,
00103 int audio_options,
00104 int video_options,
00105 int lock_compressor)
00106 {
00107 fix_codecs(asset);
00108 if(audio_options)
00109 {
00110 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
00111 format_window = window;
00112 window->create_objects();
00113 window->run_window();
00114 delete window;
00115 }
00116 else
00117 if(video_options)
00118 {
00119 MOVConfigVideo *window = new MOVConfigVideo(parent_window,
00120 asset,
00121 lock_compressor);
00122 format_window = window;
00123 window->create_objects();
00124 window->run_window();
00125 delete window;
00126 }
00127 }
00128
00129 void FileMOV::fix_codecs(Asset *asset)
00130 {
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 }
00145
00146 int FileMOV::check_sig(Asset *asset)
00147 {
00148 return quicktime_check_sig(asset->path);
00149 }
00150
00151
00152 int FileMOV::reset_parameters_derived()
00153 {
00154 fd = 0;
00155 prev_track = 0;
00156 quicktime_atracks = 0;
00157 quicktime_vtracks = 0;
00158 depth = 24;
00159 threads = 0;
00160 frames_correction = 0;
00161 samples_correction = 0;
00162 temp_float = 0;
00163 temp_allocated = 0;
00164 }
00165
00166
00167
00168
00169 int FileMOV::open_file(int rd, int wr)
00170 {
00171
00172 this->rd = rd;
00173 this->wr = wr;
00174
00175 if(suffix_number == 0) strcpy(prefix_path, asset->path);
00176
00177 if(!(fd = quicktime_open(asset->path, rd, wr)))
00178 {
00179 printf(_("FileMOV::open_file %s: No such file or directory\n"), asset->path);
00180 return 1;
00181 }
00182
00183 quicktime_set_cpus(fd, file->cpus);
00184
00185 if(rd)
00186 {
00187 format_to_asset();
00188
00189
00190 if(match4(asset->vcodec, QUICKTIME_DV))
00191 {
00192 char tc[12];
00193 dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
00194 VFrame *frame = new VFrame(0, 0, 0, BC_COMPRESSED);
00195
00196 read_frame(frame);
00197 set_video_position(0);
00198
00199 if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
00200 {
00201 dv_parse_packs(tmp_decoder, frame->get_data());
00202 dv_get_timestamp(tmp_decoder, tc);
00203 printf("Timestamp %s\n", tc);
00204
00205 float seconds = Units::text_to_seconds(tc,
00206 1,
00207 TIME_HMSF,
00208 tmp_decoder->height == 576 ? 25 : 30,
00209 0);
00210
00211 asset->tcstart = int64_t(seconds * (tmp_decoder->height == 576 ? 25 : 30));
00212 }
00213
00214 }
00215 }
00216
00217 if(wr) asset_to_format();
00218
00219
00220 quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
00221
00222
00223 quicktime_set_frame_start(fd, asset->tcstart);
00224
00225 return 0;
00226 }
00227
00228 int FileMOV::close_file()
00229 {
00230
00231 if(fd)
00232 {
00233 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
00234 quicktime_close(fd);
00235 }
00236
00237
00238 if(threads)
00239 {
00240 for(int i = 0; i < file->cpus; i++)
00241 {
00242 threads[i]->stop_encoding();
00243 delete threads[i];
00244 }
00245 delete [] threads;
00246 threads = 0;
00247 }
00248
00249
00250 threadframes.remove_all_objects();
00251
00252
00253 if(temp_float)
00254 {
00255 for(int i = 0; i < asset->channels; i++)
00256 delete [] temp_float[i];
00257 delete [] temp_float;
00258 }
00259
00260
00261 reset_parameters();
00262 FileBase::close_file();
00263
00264 return 0;
00265 }
00266
00267 void FileMOV::set_frame_start(int64_t offset)
00268 {
00269 quicktime_set_frame_start(fd, offset);
00270 }
00271
00272 void FileMOV::asset_to_format()
00273 {
00274 if(!fd) return;
00275 char audio_codec[5];
00276
00277 fix_codecs(asset);
00278
00279
00280 quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
00281 quicktime_set_info(fd, "Quicktime for Linux");
00282
00283 if(asset->audio_data)
00284 {
00285 quicktime_atracks = quicktime_set_audio(fd,
00286 asset->channels,
00287 asset->sample_rate,
00288 asset->bits,
00289 asset->acodec);
00290 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
00291 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
00292 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
00293 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
00294 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
00295 quicktime_set_parameter(fd, "mp4a_bitrate", &asset->mp4a_bitrate);
00296 }
00297
00298 if(asset->video_data)
00299 {
00300 char string[16];
00301
00302 if(!strcmp(asset->vcodec, MOV_RGBA))
00303 {
00304 strcpy(string, QUICKTIME_RAW);
00305 depth = 32;
00306 }
00307 else
00308 if(!strcmp(asset->vcodec, MOV_PNGA))
00309 {
00310 strcpy(string, QUICKTIME_PNG);
00311 depth = 32;
00312 }
00313 else
00314 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
00315 {
00316 strcpy(string, asset->vcodec);
00317 depth = 32;
00318 }
00319 else
00320 {
00321 strcpy(string, asset->vcodec);
00322 depth = 24;
00323 }
00324
00325 quicktime_vtracks = quicktime_set_video(fd,
00326 asset->layers,
00327 asset->width,
00328 asset->height,
00329 asset->frame_rate,
00330 string);
00331
00332
00333
00334 for(int i = 0; i < asset->layers; i++)
00335 quicktime_set_depth(fd, depth, i);
00336
00337 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
00338
00339
00340 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
00341 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
00342 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
00343 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
00344 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
00345 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
00346 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
00347 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
00348 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
00349 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
00350
00351 quicktime_set_parameter(fd, "ffmpeg_bitrate", &asset->ms_bitrate);
00352 quicktime_set_parameter(fd, "ffmpeg_bitrate_tolerance", &asset->ms_bitrate_tolerance);
00353 quicktime_set_parameter(fd, "ffmpeg_interlaced", &asset->ms_interlaced);
00354 quicktime_set_parameter(fd, "ffmpeg_quantizer", &asset->ms_quantization);
00355 quicktime_set_parameter(fd, "ffmpeg_gop_size", &asset->ms_gop_size);
00356 quicktime_set_parameter(fd, "ffmpeg_fix_bitrate", &asset->ms_fix_bitrate);
00357
00358 quicktime_set_parameter(fd, "h264_bitrate", &asset->h264_bitrate);
00359 quicktime_set_parameter(fd, "h264_quantizer", &asset->h264_quantizer);
00360 quicktime_set_parameter(fd, "h264_fix_bitrate", &asset->h264_fix_bitrate);
00361
00362
00363 }
00364
00365
00366
00367
00368
00369 if(wr && asset->format == FILE_AVI)
00370 {
00371 quicktime_set_avi(fd, 1);
00372 }
00373 }
00374
00375
00376 void FileMOV::format_to_asset()
00377 {
00378 if(!fd) return;
00379
00380 if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
00381 asset->audio_data = quicktime_has_audio(fd);
00382 if(asset->audio_data)
00383 {
00384 asset->channels = 0;
00385 int qt_tracks = quicktime_audio_tracks(fd);
00386 for(int i = 0; i < qt_tracks; i++)
00387 asset->channels += quicktime_track_channels(fd, i);
00388
00389 if(!asset->sample_rate)
00390 asset->sample_rate = quicktime_sample_rate(fd, 0);
00391 asset->bits = quicktime_audio_bits(fd, 0);
00392 asset->audio_length = quicktime_audio_length(fd, 0);
00393 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
00394 }
00395
00396
00397 if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
00398 asset->video_data = 1;
00399
00400 if(asset->video_data)
00401 {
00402 depth = quicktime_video_depth(fd, 0);
00403 asset->layers = quicktime_video_tracks(fd);
00404 asset->width = quicktime_video_width(fd, 0);
00405 asset->height = quicktime_video_height(fd, 0);
00406 asset->video_length = quicktime_video_length(fd, 0);
00407
00408 if(!asset->frame_rate)
00409 asset->frame_rate = quicktime_frame_rate(fd, 0);
00410 if(!asset->interlace_mode)
00411 asset->interlace_mode = quicktime_video_interlacemode(fd, 0);
00412
00413 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
00414 }
00415 }
00416
00417 int FileMOV::colormodel_supported(int colormodel)
00418 {
00419 return colormodel;
00420 }
00421
00422 int FileMOV::get_best_colormodel(Asset *asset, int driver)
00423 {
00424 switch(driver)
00425 {
00426 case PLAYBACK_X11:
00427 return BC_RGB888;
00428 break;
00429 case PLAYBACK_X11_XV:
00430 if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
00431 if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422P;
00432 if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
00433 if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
00434 if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
00435 if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
00436 if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
00437 if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
00438 if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
00439 if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
00440 if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
00441 if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
00442 if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
00443 if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
00444 break;
00445 case PLAYBACK_DV1394:
00446 case PLAYBACK_FIREWIRE:
00447 if(match4(asset->vcodec, QUICKTIME_DV) ||
00448 match4(asset->vcodec, QUICKTIME_DVSD)) return BC_COMPRESSED;
00449 return BC_YUV422P;
00450 break;
00451 case PLAYBACK_LML:
00452 case PLAYBACK_BUZ:
00453 if(match4(asset->vcodec, QUICKTIME_MJPA))
00454 return BC_COMPRESSED;
00455 else
00456 return BC_YUV422P;
00457 break;
00458 case VIDEO4LINUX:
00459 case VIDEO4LINUX2:
00460 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
00461 else
00462 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
00463 else
00464 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
00465 else
00466 if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
00467 else
00468 if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
00469 else
00470 if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
00471 else
00472 if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
00473 else
00474 if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
00475 else
00476 if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
00477 break;
00478 case CAPTURE_BUZ:
00479 case CAPTURE_LML:
00480 case VIDEO4LINUX2JPEG:
00481 if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4))
00482 return BC_COMPRESSED;
00483 else
00484 return BC_YUV422;
00485 break;
00486 case CAPTURE_FIREWIRE:
00487 case CAPTURE_IEC61883:
00488 if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
00489 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4))
00490 return BC_COMPRESSED;
00491 else
00492 return BC_YUV422;
00493 break;
00494 }
00495 return BC_RGB888;
00496 }
00497
00498 int FileMOV::can_copy_from(Edit *edit, int64_t position)
00499 {
00500 if(!fd) return 0;
00501
00502
00503 if(edit->asset->format == FILE_JPEG_LIST &&
00504 match4(this->asset->vcodec, QUICKTIME_JPEG))
00505 return 1;
00506 else
00507 if((edit->asset->format == FILE_MOV ||
00508 edit->asset->format == FILE_AVI))
00509 {
00510 if(match4(edit->asset->vcodec, this->asset->vcodec))
00511 return 1;
00512
00513
00514 int is_edit_dv = 0;
00515 int is_this_dv = 0;
00516 if (match4(edit->asset->vcodec, QUICKTIME_DV) ||
00517 match4(edit->asset->vcodec, QUICKTIME_DVSD))
00518 is_edit_dv = 1;
00519 if (match4(this->asset->vcodec, QUICKTIME_DV) ||
00520 match4(this->asset->vcodec, QUICKTIME_DVSD))
00521 is_this_dv = 1;
00522 if (is_this_dv && is_edit_dv)
00523 return 1;
00524 }
00525 else
00526 if(edit->asset->format == FILE_RAWDV)
00527 {
00528 if(match4(this->asset->vcodec, QUICKTIME_DV) || match4(this->asset->vcodec, QUICKTIME_DVSD))
00529 return 1;
00530 }
00531
00532
00533 return 0;
00534 }
00535
00536
00537 int64_t FileMOV::get_audio_length()
00538 {
00539 if(!fd) return 0;
00540 int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
00541
00542 return result;
00543 }
00544
00545 int FileMOV::set_audio_position(int64_t x)
00546 {
00547 if(!fd) return 1;
00548
00549 if(x >= 0 && x < asset->audio_length)
00550 return quicktime_set_audio_position(fd, x, 0);
00551 else
00552 return 1;
00553 }
00554
00555 int FileMOV::set_video_position(int64_t x)
00556 {
00557 if(!fd) return 1;
00558 if(x >= 0 && x < asset->video_length)
00559 {
00560 int result = quicktime_set_video_position(fd, x, file->current_layer);
00561 return result;
00562 }else
00563 return 1;
00564 }
00565
00566
00567 void FileMOV::new_audio_temp(int64_t len)
00568 {
00569 if(temp_allocated && temp_allocated < len)
00570 {
00571 for(int i = 0; i < asset->channels; i++)
00572 delete [] temp_float[i];
00573 delete [] temp_float;
00574 temp_allocated = 0;
00575 }
00576
00577 if(!temp_allocated)
00578 {
00579 temp_allocated = len;
00580 temp_float = new float*[asset->channels];
00581 for(int i = 0; i < asset->channels; i++)
00582 temp_float[i] = new float[len];
00583 }
00584 }
00585
00586
00587
00588 int FileMOV::write_samples(double **buffer, int64_t len)
00589 {
00590 int i, j;
00591 int64_t bytes;
00592 int result = 0, track_channels = 0;
00593 int chunk_size;
00594
00595 if(!fd) return 0;
00596
00597 if(quicktime_supported_audio(fd, 0))
00598 {
00599
00600
00601 new_audio_temp(len);
00602
00603
00604 for(i = 0; i < asset->channels; i++)
00605 {
00606 for(j = 0; j < len; j++)
00607 {
00608 temp_float[i][j] = buffer[i][j];
00609 }
00610 }
00611
00612
00613
00614 float **channel_ptr;
00615 channel_ptr = new float*[asset->channels];
00616
00617 for(j = 0; j < len && !result; )
00618 {
00619 chunk_size = asset->sample_rate;
00620 if(j + chunk_size > len) chunk_size = len - j;
00621
00622 for(i = 0; i < asset->channels; i++)
00623 {
00624 channel_ptr[i] = &temp_float[i][j];
00625 }
00626
00627 result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
00628 j += asset->sample_rate;
00629 }
00630
00631 delete [] channel_ptr;
00632 }
00633 return result;
00634 }
00635
00636 int FileMOV::write_frames(VFrame ***frames, int len)
00637 {
00638
00639 int i, j, k, result = 0;
00640 int default_compressor = 1;
00641 if(!fd) return 0;
00642
00643 for(i = 0; i < asset->layers && !result; i++)
00644 {
00645
00646
00647
00648
00649
00650
00651 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
00652 {
00653 default_compressor = 0;
00654 for(j = 0; j < len && !result; j++)
00655 {
00656 VFrame *frame = frames[i][j];
00657
00658
00659
00660
00661
00662
00663 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
00664 !strcmp(asset->vcodec, QUICKTIME_H263) ||
00665 !strcmp(asset->vcodec, QUICKTIME_HV60))
00666 {
00667 if(quicktime_mpeg4_is_key(frame->get_data(),
00668 frame->get_compressed_size(),
00669 asset->vcodec))
00670 quicktime_insert_keyframe(fd, file->current_frame + j, i);
00671
00672
00673
00674 if(!(file->current_frame + j) &&
00675 !quicktime_mpeg4_has_vol(frame->get_data()))
00676 {
00677 VFrame *temp_frame = new VFrame;
00678
00679 temp_frame->allocate_compressed_data(frame->get_compressed_size() +
00680 0xff);
00681 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
00682 asset->width,
00683 asset->height,
00684 60000,
00685 asset->frame_rate);
00686 memcpy(temp_frame->get_data() + bytes,
00687 frame->get_data(),
00688 frame->get_compressed_size());
00689 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
00690
00691 result = quicktime_write_frame(fd,
00692 temp_frame->get_data(),
00693 temp_frame->get_compressed_size(),
00694 i);
00695
00696 delete temp_frame;
00697
00698
00699 }
00700 else
00701 {
00702 result = quicktime_write_frame(fd,
00703 frame->get_data(),
00704 frame->get_compressed_size(),
00705 i);
00706 }
00707 }
00708 else
00709
00710 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
00711 !strcmp(asset->vcodec, QUICKTIME_HV64) ||
00712 !strcmp(asset->vcodec, QUICKTIME_MP4V))
00713 {
00714 if(frame->get_keyframe() || file->current_frame + j == 0)
00715 quicktime_insert_keyframe(fd, file->current_frame + j, i);
00716
00717
00718 result = quicktime_write_frame(fd,
00719 frame->get_data(),
00720 frame->get_compressed_size(),
00721 i);
00722 }
00723 else
00724 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
00725 {
00726 if(quicktime_mpeg4_is_key(frame->get_data(),
00727 frame->get_compressed_size(),
00728 asset->vcodec))
00729 quicktime_insert_keyframe(fd, file->current_frame + j, i);
00730 result = quicktime_write_frame(fd,
00731 frame->get_data(),
00732 frame->get_compressed_size(),
00733 i);
00734 }
00735 else
00736 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
00737 {
00738 long field2_offset;
00739
00740
00741 if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
00742 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
00743
00744 unsigned char *data = frame->get_data();
00745 long data_size = frame->get_compressed_size();
00746 long data_allocated = frame->get_compressed_allocated();
00747
00748
00749 if(data_size)
00750 {
00751 if(asset->format == FILE_MOV)
00752 {
00753 mjpeg_insert_quicktime_markers(&data,
00754 &data_size,
00755 &data_allocated,
00756 2,
00757 &field2_offset);
00758 }
00759 else
00760 {
00761 mjpeg_insert_avi_markers(&data,
00762 &data_size,
00763 &data_allocated,
00764 2,
00765 &field2_offset);
00766 }
00767 frame->set_compressed_size(data_size);
00768 result = quicktime_write_frame(fd,
00769 frame->get_data(),
00770 frame->get_compressed_size(),
00771 i);
00772 }
00773 else
00774 printf("FileMOV::write_frames data_size=%d\n", data_size);
00775 }
00776 else
00777 result = quicktime_write_frame(fd,
00778 frame->get_data(),
00779 frame->get_compressed_size(),
00780 i);
00781
00782
00783 }
00784 }
00785 else
00786 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
00787 match4(asset->vcodec, QUICKTIME_YUV422) ||
00788 match4(asset->vcodec, QUICKTIME_RAW))
00789 {
00790
00791 default_compressor = 0;
00792 for(j = 0; j < len && !result; j++)
00793 {
00794 VFrame *frame = frames[i][j];
00795
00796 quicktime_set_cmodel(fd, frame->get_color_model());
00797 if(cmodel_is_planar(frame->get_color_model()))
00798 {
00799 unsigned char *planes[3];
00800 planes[0] = frame->get_y();
00801 planes[1] = frame->get_u();
00802 planes[2] = frame->get_v();
00803 result = quicktime_encode_video(fd, planes, i);
00804 }
00805 else
00806 {
00807 result = quicktime_encode_video(fd, frame->get_rows(), i);
00808
00809 }
00810
00811 }
00812 }
00813 else
00814 if(file->cpus > 1 &&
00815 (match4(asset->vcodec, QUICKTIME_JPEG) ||
00816 match4(asset->vcodec, QUICKTIME_MJPA)))
00817 {
00818 default_compressor = 0;
00819
00820 ThreadStruct *threadframe;
00821 int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
00822
00823
00824 if(!threads)
00825 {
00826 threads = new FileMOVThread*[file->cpus];
00827 for(j = 0; j < file->cpus; j++)
00828 {
00829 threads[j] = new FileMOVThread(this, fields);
00830 threads[j]->start_encoding();
00831 }
00832 }
00833
00834
00835
00836
00837 while(threadframes.total < len)
00838 {
00839 threadframes.append(threadframe = new ThreadStruct);
00840 }
00841
00842
00843 for(j = 0; j < len; j++)
00844 {
00845 VFrame *frame = frames[i][j];
00846 threadframes.values[j]->input = frame;
00847 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
00848 }
00849 total_threadframes = len;
00850 current_threadframe = 0;
00851
00852
00853 for(j = 0; j < file->cpus; j++)
00854 {
00855 threads[j]->encode_buffer();
00856 }
00857
00858
00859
00860 for(j = 0; j < len; j++)
00861 {
00862 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
00863 threadframes.values[j]->completion_lock->unlock();
00864 if(!result)
00865 {
00866 result = quicktime_write_frame(fd,
00867 threadframes.values[j]->output,
00868 threadframes.values[j]->output_size,
00869 i);
00870 }
00871 }
00872 }
00873
00874 if(default_compressor)
00875 {
00876
00877
00878 for(j = 0; j < len && !result; j++)
00879 {
00880
00881 VFrame *frame = frames[i][j];
00882 quicktime_set_cmodel(fd, frame->get_color_model());
00883
00884 if(cmodel_is_planar(frame->get_color_model()))
00885 {
00886 unsigned char *planes[3];
00887 planes[0] = frame->get_y();
00888 planes[1] = frame->get_u();
00889 planes[2] = frame->get_v();
00890 result = quicktime_encode_video(fd, planes, i);
00891 }
00892 else
00893 {
00894 result = quicktime_encode_video(fd, frame->get_rows(), i);
00895 }
00896 }
00897 }
00898
00899 }
00900
00901
00902
00903 return result;
00904 }
00905
00906
00907
00908 int FileMOV::read_frame(VFrame *frame)
00909 {
00910 if(!fd) return 1;
00911 int result = 0;
00912
00913 switch(frame->get_color_model())
00914 {
00915 case BC_COMPRESSED:
00916 frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
00917 frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
00918 frame->set_keyframe((quicktime_get_keyframe_before(fd,
00919 file->current_frame,
00920 file->current_layer) == file->current_frame));
00921
00922 result = quicktime_read_frame(fd,
00923 frame->get_data(),
00924 file->current_layer);
00925 break;
00926
00927
00928 case BC_YUV420P:
00929 case BC_YUV422P:
00930 {
00931 unsigned char *row_pointers[3];
00932 row_pointers[0] = frame->get_y();
00933 row_pointers[1] = frame->get_u();
00934 row_pointers[2] = frame->get_v();
00935
00936 quicktime_set_cmodel(fd, frame->get_color_model());
00937 quicktime_decode_video(fd,
00938 row_pointers,
00939 file->current_layer);
00940 }
00941 break;
00942
00943
00944 default:
00945 quicktime_set_cmodel(fd, frame->get_color_model());
00946 result = quicktime_decode_video(fd,
00947 frame->get_rows(),
00948 file->current_layer);
00949
00950 break;
00951 }
00952
00953
00954
00955 return result;
00956 }
00957
00958
00959
00960 int64_t FileMOV::compressed_frame_size()
00961 {
00962 if(!fd) return 0;
00963 return quicktime_frame_size(fd, file->current_frame, file->current_layer);
00964 }
00965
00966 int FileMOV::read_compressed_frame(VFrame *buffer)
00967 {
00968 int64_t result;
00969 if(!fd) return 0;
00970
00971 result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
00972 buffer->set_compressed_size(result);
00973 buffer->set_keyframe((quicktime_get_keyframe_before(fd,
00974 file->current_frame,
00975 file->current_layer) == file->current_frame));
00976 result = !result;
00977 return result;
00978 }
00979
00980 int FileMOV::write_compressed_frame(VFrame *buffer)
00981 {
00982 int result = 0;
00983 if(!fd) return 0;
00984
00985 result = quicktime_write_frame(fd,
00986 buffer->get_data(),
00987 buffer->get_compressed_size(),
00988 file->current_layer);
00989 return result;
00990 }
00991
00992
00993
00994 int FileMOV::read_raw(VFrame *frame,
00995 float in_x1, float in_y1, float in_x2, float in_y2,
00996 float out_x1, float out_y1, float out_x2, float out_y2,
00997 int use_float, int interpolate)
00998 {
00999 int64_t i, color_channels, result = 0;
01000 if(!fd) return 0;
01001
01002 quicktime_set_video_position(fd, file->current_frame, file->current_layer);
01003
01004 switch(frame->get_color_model())
01005 {
01006 case BC_RGB888:
01007 result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
01008 break;
01009 case BC_RGBA8888:
01010 break;
01011 case BC_RGB161616:
01012 break;
01013 case BC_RGBA16161616:
01014 break;
01015 case BC_YUV888:
01016 break;
01017 case BC_YUVA8888:
01018 break;
01019 case BC_YUV161616:
01020 break;
01021 case BC_YUVA16161616:
01022 break;
01023 case BC_YUV420P:
01024 break;
01025 }
01026 return result;
01027 }
01028
01029
01030 int FileMOV::read_samples(double *buffer, int64_t len)
01031 {
01032 int qt_track, qt_channel;
01033
01034 if(!fd) return 0;
01035
01036 if(quicktime_track_channels(fd, 0) > file->current_channel &&
01037 quicktime_supported_audio(fd, 0))
01038 {
01039
01040
01041 new_audio_temp(len);
01042
01043
01044 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
01045 {
01046 printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
01047 return 1;
01048 }
01049 else
01050 {
01051 for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 }
01063
01064 return 0;
01065 }
01066
01067
01068 char* FileMOV::strtocompression(char *string)
01069 {
01070 if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
01071 if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
01072 if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
01073 if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
01074 if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
01075 if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
01076 if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
01077 if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DVSD;
01078
01079 if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
01080 if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
01081 if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
01082 if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
01083 if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
01084 if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
01085 if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
01086 if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
01087 if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
01088 if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
01089 if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
01090 if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
01091
01092 if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
01093 if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
01094 if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
01095 if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
01096 if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
01097 if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
01098 if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
01099
01100
01101
01102 return QUICKTIME_RAW;
01103 }
01104
01105 char* FileMOV::compressiontostr(char *string)
01106 {
01107 if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
01108 if(match4(string, QUICKTIME_H264)) return