00001 #include "asset.h"
00002 #include "bcprogressbox.h"
00003 #include "bcsignals.h"
00004 #include "bitspopup.h"
00005 #include "byteorder.h"
00006 #include "clip.h"
00007 #include "condition.h"
00008 #include "edit.h"
00009 #include "file.h"
00010 #include "filempeg.h"
00011 #include "filesystem.h"
00012 #include "guicast.h"
00013 #include "indexfile.h"
00014 #include "interlacemodes.h"
00015 #include "language.h"
00016 #include "mwindow.inc"
00017 #include "preferences.h"
00018 #include "vframe.h"
00019 #include "videodevice.inc"
00020
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024
00025 #define MPEG_YUV420 0
00026 #define MPEG_YUV422 1
00027
00028
00029 #define MJPEG_EXE PLUGIN_DIR "/mpeg2enc.plugin"
00030
00031
00032
00033
00034
00035
00036
00037
00038 static double frame_rate_codes[] =
00039 {
00040 0,
00041 24000.0/1001.0,
00042 24.0,
00043 25.0,
00044 30000.0/1001.0,
00045 30.0,
00046 50.0,
00047 60000.0/1001.0,
00048 60.0
00049 };
00050
00051 static double aspect_ratio_codes[] =
00052 {
00053 0,
00054 1.0,
00055 1.333,
00056 1.777,
00057 2.11
00058 };
00059
00060
00061
00062
00063
00064
00065
00066
00067 FileMPEG::FileMPEG(Asset *asset, File *file)
00068 : FileBase(asset, file)
00069 {
00070 reset_parameters();
00071
00072 if(asset->format == FILE_UNKNOWN) asset->format = FILE_MPEG;
00073 asset->byte_order = 0;
00074 next_frame_lock = new Condition(0, "FileMPEG::next_frame_lock");
00075 next_frame_done = new Condition(0, "FileMPEG::next_frame_done");
00076 }
00077
00078 FileMPEG::~FileMPEG()
00079 {
00080 close_file();
00081 delete next_frame_lock;
00082 delete next_frame_done;
00083 }
00084
00085 void FileMPEG::get_parameters(BC_WindowBase *parent_window,
00086 Asset *asset,
00087 BC_WindowBase* &format_window,
00088 int audio_options,
00089 int video_options)
00090 {
00091 if(audio_options && asset->format == FILE_AMPEG)
00092 {
00093 MPEGConfigAudio *window = new MPEGConfigAudio(parent_window, asset);
00094 format_window = window;
00095 window->create_objects();
00096 window->run_window();
00097 delete window;
00098 }
00099 else
00100 if(video_options && asset->format == FILE_VMPEG)
00101 {
00102 MPEGConfigVideo *window = new MPEGConfigVideo(parent_window, asset);
00103 format_window = window;
00104 window->create_objects();
00105 window->run_window();
00106 delete window;
00107 }
00108 }
00109
00110 int FileMPEG::check_sig(Asset *asset)
00111 {
00112 return mpeg3_check_sig(asset->path);
00113 }
00114
00115 int FileMPEG::reset_parameters_derived()
00116 {
00117 wrote_header = 0;
00118 mjpeg_out = 0;
00119 mjpeg_eof = 0;
00120 mjpeg_error = 0;
00121
00122
00123
00124 fd = 0;
00125 video_out = 0;
00126 audio_out = 0;
00127 prev_track = 0;
00128 temp_frame = 0;
00129 toolame_temp = 0;
00130 toolame_allocation = 0;
00131 toolame_result = 0;
00132 lame_temp[0] = 0;
00133 lame_temp[1] = 0;
00134 lame_allocation = 0;
00135 lame_global = 0;
00136 lame_output = 0;
00137 lame_output_allocation = 0;
00138 lame_fd = 0;
00139 lame_started = 0;
00140 }
00141
00142
00143
00144
00145 int FileMPEG::open_file(int rd, int wr)
00146 {
00147 int result = 0;
00148 this->rd = rd;
00149 this->wr = wr;
00150
00151 if(rd)
00152 {
00153 if(!(fd = mpeg3_open(asset->path)))
00154 {
00155 printf("FileMPEG::open_file %s\n", asset->path);
00156 result = 1;
00157 }
00158 else
00159 {
00160
00161 if(!mpeg3_has_toc(fd))
00162 {
00163
00164 if(mpeg3_total_vstreams(fd))
00165 {
00166 if(create_index()) return 1;
00167 }
00168 }
00169
00170 mpeg3_set_cpus(fd, file->cpus);
00171
00172 asset->audio_data = mpeg3_has_audio(fd);
00173 if(asset->audio_data)
00174 {
00175 asset->channels = 0;
00176 for(int i = 0; i < mpeg3_total_astreams(fd); i++)
00177 {
00178 asset->channels += mpeg3_audio_channels(fd, i);
00179 }
00180 if(!asset->sample_rate)
00181 asset->sample_rate = mpeg3_sample_rate(fd, 0);
00182 asset->audio_length = mpeg3_audio_samples(fd, 0);
00183 }
00184
00185 asset->video_data = mpeg3_has_video(fd);
00186 if(asset->video_data)
00187 {
00188 asset->layers = mpeg3_total_vstreams(fd);
00189 asset->width = mpeg3_video_width(fd, 0);
00190 asset->height = mpeg3_video_height(fd, 0);
00191 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED;
00192
00193 asset->video_length = mpeg3_video_frames(fd, 0);
00194 asset->vmpeg_cmodel =
00195 (mpeg3_colormodel(fd, 0) == MPEG3_YUV422P) ? MPEG_YUV422 : MPEG_YUV420;
00196 if(!asset->frame_rate)
00197 asset->frame_rate = mpeg3_frame_rate(fd, 0);
00198 }
00199 }
00200 }
00201
00202
00203
00204 if(wr && asset->format == FILE_VMPEG)
00205 {
00206
00207 if(asset->vmpeg_cmodel == MPEG_YUV422)
00208 {
00209 char bitrate_string[BCTEXTLEN];
00210 char quant_string[BCTEXTLEN];
00211 char iframe_string[BCTEXTLEN];
00212
00213 sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
00214 sprintf(quant_string, "%d", asset->vmpeg_quantization);
00215 sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
00216
00217
00218 if(!result)
00219 {
00220 append_vcommand_line("mpeg2enc");
00221
00222
00223 if(asset->aspect_ratio > 0)
00224 {
00225 append_vcommand_line("-a");
00226 if(EQUIV(asset->aspect_ratio, 1))
00227 append_vcommand_line("1");
00228 else
00229 if(EQUIV(asset->aspect_ratio, 1.333))
00230 append_vcommand_line("2");
00231 else
00232 if(EQUIV(asset->aspect_ratio, 1.777))
00233 append_vcommand_line("3");
00234 else
00235 if(EQUIV(asset->aspect_ratio, 2.11))
00236 append_vcommand_line("4");
00237 }
00238
00239 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
00240 append_vcommand_line(asset->vmpeg_cmodel == MPEG_YUV422 ? "-422" : "");
00241 if(asset->vmpeg_fix_bitrate)
00242 {
00243 append_vcommand_line("-b");
00244 append_vcommand_line(bitrate_string);
00245 }
00246 else
00247 {
00248 append_vcommand_line("-q");
00249 append_vcommand_line(quant_string);
00250 }
00251 append_vcommand_line(!asset->vmpeg_fix_bitrate ? quant_string : "");
00252 append_vcommand_line("-n");
00253 append_vcommand_line(iframe_string);
00254 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
00255 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
00256 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
00257 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
00258 append_vcommand_line(asset->path);
00259
00260 video_out = new FileMPEGVideo(this);
00261 video_out->start();
00262 }
00263 }
00264 else
00265
00266 {
00267 char string[BCTEXTLEN];
00268 sprintf(mjpeg_command, MJPEG_EXE);
00269
00270 if(asset->vmpeg_fix_bitrate)
00271 {
00272 sprintf(string, " -b %d -q %d", asset->vmpeg_bitrate, 0);
00273 }
00274 else
00275 {
00276 sprintf(string, " -b %d -q %d", asset->vmpeg_bitrate, asset->vmpeg_quantization);
00277 }
00278 strcat(mjpeg_command, string);
00279
00280
00281
00282
00283
00284
00285
00286 int aspect_ratio_code = -1;
00287 if(asset->aspect_ratio > 0)
00288 {
00289 for(int i = 0; i < sizeof(aspect_ratio_codes) / sizeof(double); i++)
00290 {
00291 if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
00292 {
00293 aspect_ratio_code = i;
00294 break;
00295 }
00296 }
00297 }
00298 if(aspect_ratio_code < 0)
00299 {
00300 printf("FileMPEG::open_file: Unsupported aspect ratio %f\n", asset->aspect_ratio);
00301 aspect_ratio_code = 2;
00302 }
00303 sprintf(string, " -a %d", aspect_ratio_code);
00304 strcat(mjpeg_command, string);
00305
00306
00307
00308
00309
00310
00311
00312 int frame_rate_code = -1;
00313 for(int i = 1; sizeof(frame_rate_codes) / sizeof(double); ++i)
00314 {
00315 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
00316 {
00317 frame_rate_code = i;
00318 break;
00319 }
00320 }
00321 if(frame_rate_code < 0)
00322 {
00323 frame_rate_code = 4;
00324 printf("FileMPEG::open_file: Unsupported frame rate %f\n", asset->frame_rate);
00325 }
00326 sprintf(string, " -F %d", frame_rate_code);
00327 strcat(mjpeg_command, string);
00328
00329
00330
00331
00332
00333 strcat(mjpeg_command, asset->vmpeg_progressive ? " -I 0" : " -I 1");
00334
00335
00336
00337 sprintf(string, " -M %d", file->cpus);
00338 strcat(mjpeg_command, string);
00339
00340
00341 if(!asset->vmpeg_progressive)
00342 {
00343 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
00344 }
00345
00346
00347 sprintf(string, " -f %d", asset->vmpeg_preset);
00348 strcat(mjpeg_command, string);
00349
00350
00351 sprintf(string, " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
00352 strcat(mjpeg_command, string);
00353
00354
00355 if(asset->vmpeg_seq_codes) strcat(mjpeg_command, " -s");
00356
00357
00358 sprintf(string, " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
00359 strcat(mjpeg_command, string);
00360
00361 sprintf(string, " -o %s", asset->path);
00362 strcat(mjpeg_command, string);
00363
00364
00365
00366 printf("FileMPEG::open_file: Running %s\n", mjpeg_command);
00367 if(!(mjpeg_out = popen(mjpeg_command, "w")))
00368 {
00369 perror("FileMPEG::open_file");
00370 }
00371
00372 video_out = new FileMPEGVideo(this);
00373 video_out->start();
00374 }
00375 }
00376
00377 if(wr && asset->format == FILE_AMPEG)
00378 {
00379 char command_line[BCTEXTLEN];
00380 char encoder_string[BCTEXTLEN];
00381 char argument_string[BCTEXTLEN];
00382
00383
00384 encoder_string[0] = 0;
00385
00386 if(asset->ampeg_derivative == 2)
00387 {
00388 char string[BCTEXTLEN];
00389 append_acommand_line("toolame");
00390 append_acommand_line("-m");
00391 append_acommand_line((asset->channels >= 2) ? "j" : "m");
00392 sprintf(string, "%f", (float)asset->sample_rate / 1000);
00393 append_acommand_line("-s");
00394 append_acommand_line(string);
00395 sprintf(string, "%d", asset->ampeg_bitrate);
00396 append_acommand_line("-b");
00397 append_acommand_line(string);
00398 append_acommand_line("-");
00399 append_acommand_line(asset->path);
00400
00401 audio_out = new FileMPEGAudio(this);
00402 audio_out->start();
00403 }
00404 else
00405 if(asset->ampeg_derivative == 3)
00406 {
00407 lame_global = lame_init();
00408 lame_set_brate(lame_global, asset->ampeg_bitrate / 1000);
00409 lame_set_quality(lame_global, 0);
00410 lame_set_in_samplerate(lame_global,
00411 asset->sample_rate);
00412 if((result = lame_init_params(lame_global)) < 0)
00413 {
00414 printf(_("encode: lame_init_params returned %d\n"), result);
00415 lame_close(lame_global);
00416 lame_global = 0;
00417 }
00418 else
00419 if(!(lame_fd = fopen(asset->path, "w")))
00420 {
00421 perror("FileMPEG::open_file");
00422 lame_close(lame_global);
00423 lame_global = 0;
00424 }
00425 }
00426 else
00427 {
00428 printf("FileMPEG::open_file: ampeg_derivative=%d\n", asset->ampeg_derivative);
00429 result = 1;
00430 }
00431 }
00432
00433
00434
00435 return result;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445 int FileMPEG::create_index()
00446 {
00447
00448 char index_filename[BCTEXTLEN];
00449 char source_filename[BCTEXTLEN];
00450 IndexFile::get_index_filename(source_filename,
00451 file->preferences->index_directory,
00452 index_filename,
00453 asset->path);
00454 char *ptr = strrchr(index_filename, '.');
00455 if(!ptr) return 1;
00456
00457 sprintf(ptr, ".toc");
00458
00459
00460 FILE *test = fopen(index_filename, "r");
00461 if(test)
00462 {
00463
00464 fclose(test);
00465 }
00466 else
00467 {
00468
00469
00470 char progress_title[BCTEXTLEN];
00471 char string[BCTEXTLEN];
00472 sprintf(progress_title, "Creating %s\n", index_filename);
00473 int64_t total_bytes;
00474 mpeg3_t *index_file = mpeg3_start_toc(asset->path, index_filename, &total_bytes);
00475 struct timeval new_time;
00476 struct timeval prev_time;
00477 struct timeval start_time;
00478 struct timeval current_time;
00479 gettimeofday(&prev_time, 0);
00480 gettimeofday(&start_time, 0);
00481
00482 BC_ProgressBox *progress = new BC_ProgressBox(-1,
00483 -1,
00484 progress_title,
00485 total_bytes);
00486 progress->start();
00487 int result = 0;
00488 while(1)
00489 {
00490 int64_t bytes_processed;
00491 mpeg3_do_toc(index_file, &bytes_processed);
00492 gettimeofday(&new_time, 0);
00493
00494 if(new_time.tv_sec - prev_time.tv_sec >= 1)
00495 {
00496 gettimeofday(¤t_time, 0);
00497 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
00498 int64_t total_seconds = elapsed_seconds * total_bytes / bytes_processed;
00499 int64_t eta = total_seconds - elapsed_seconds;
00500 progress->update(bytes_processed, 1);
00501 sprintf(string,
00502 "%sETA: %lldm%llds",
00503 progress_title,
00504 eta / 60,
00505 eta % 60);
00506 progress->update_title(string, 1);
00507
00508
00509
00510
00511
00512 prev_time = new_time;
00513 }
00514 if(bytes_processed >= total_bytes) break;
00515 if(progress->is_cancelled())
00516 {
00517 result = 1;
00518 break;
00519 }
00520 }
00521
00522 mpeg3_stop_toc(index_file);
00523
00524 progress->stop_progress();
00525 delete progress;
00526 if(result)
00527 {
00528 remove(index_filename);
00529 return 1;
00530 }
00531 }
00532
00533
00534
00535
00536
00537 if(fd) mpeg3_close(fd);
00538 if(!(fd = mpeg3_open(index_filename)))
00539 {
00540 return 1;
00541 }
00542 else
00543 return 0;
00544 }
00545
00546
00547
00548
00549
00550
00551 void FileMPEG::append_vcommand_line(const char *string)
00552 {
00553 if(string[0])
00554 {
00555 char *argv = strdup(string);
00556 vcommand_line.append(argv);
00557 }
00558 }
00559
00560 void FileMPEG::append_acommand_line(const char *string)
00561 {
00562 if(string[0])
00563 {
00564 char *argv = strdup(string);
00565 acommand_line.append(argv);
00566 }
00567 }
00568
00569
00570 int FileMPEG::close_file()
00571 {
00572 mjpeg_eof = 1;
00573 next_frame_lock->unlock();
00574
00575 if(fd)
00576 {
00577 mpeg3_close(fd);
00578 }
00579
00580 if(video_out)
00581 {
00582
00583 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
00584 {
00585 mpeg2enc_set_input_buffers(1, 0, 0, 0);
00586 }
00587 delete video_out;
00588 video_out = 0;
00589 }
00590
00591 vcommand_line.remove_all_objects();
00592 acommand_line.remove_all_objects();
00593
00594 if(audio_out)
00595 {
00596 toolame_send_buffer(0, 0);
00597 delete audio_out;
00598 audio_out = 0;
00599 }
00600
00601 if(lame_global)
00602 lame_close(lame_global);
00603
00604 if(temp_frame) delete temp_frame;
00605 if(toolame_temp) delete [] toolame_temp;
00606
00607 if(lame_temp[0]) delete [] lame_temp[0];
00608 if(lame_temp[1]) delete [] lame_temp[1];
00609 if(lame_output) delete [] lame_output;
00610 if(lame_fd) fclose(lame_fd);
00611
00612 if(mjpeg_out) fclose(mjpeg_out);
00613 reset_parameters();
00614
00615 FileBase::close_file();
00616 return 0;
00617 }
00618
00619 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
00620 {
00621
00622 switch(driver)
00623 {
00624 case PLAYBACK_X11:
00625 return BC_RGB888;
00626 if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
00627 if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
00628 break;
00629 case PLAYBACK_X11_XV:
00630 if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
00631 if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
00632 break;
00633 case PLAYBACK_LML:
00634 case PLAYBACK_BUZ:
00635 return BC_YUV422P;
00636 break;
00637 case PLAYBACK_DV1394:
00638 case PLAYBACK_FIREWIRE:
00639 return BC_YUV422P;
00640 break;
00641 case VIDEO4LINUX:
00642 case VIDEO4LINUX2:
00643 if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
00644 if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
00645 break;
00646 case CAPTURE_BUZ:
00647 case CAPTURE_LML:
00648 return BC_YUV422;
00649 break;
00650 case CAPTURE_FIREWIRE:
00651 case CAPTURE_IEC61883:
00652 return BC_YUV422P;
00653 break;
00654 }
00655
00656 }
00657
00658 int FileMPEG::colormodel_supported(int colormodel)
00659 {
00660 return colormodel;
00661 }
00662
00663 int FileMPEG::get_index(char *index_path)
00664 {
00665 if(!fd) return 1;
00666
00667
00668
00669 if(mpeg3_index_tracks(fd))
00670 {
00671
00672 int buffer_size = 0;
00673 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
00674 {
00675 buffer_size += mpeg3_index_size(fd, i) *
00676 mpeg3_index_channels(fd, i) *
00677 2;
00678 }
00679
00680 asset->index_buffer = new float[buffer_size];
00681
00682
00683 int current_offset = 0;
00684
00685 int current_channel = 0;
00686 asset->index_zoom = mpeg3_index_zoom(fd);
00687 asset->index_offsets = new int64_t[asset->channels];
00688 asset->index_sizes = new int64_t[asset->channels];
00689 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
00690 {
00691 for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
00692 {
00693 asset->index_offsets[current_channel] = current_offset;
00694 asset->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
00695 memcpy(asset->index_buffer + current_offset,
00696 mpeg3_index_data(fd, i, j),
00697 mpeg3_index_size(fd, i) * sizeof(float) * 2);
00698
00699 current_offset += mpeg3_index_size(fd, i) * 2;
00700 current_channel++;
00701 }
00702 }
00703
00704 FileSystem fs;
00705 asset->index_bytes = fs.get_size(asset->path);
00706
00707 asset->write_index(index_path, buffer_size * sizeof(float));
00708 delete [] asset->index_buffer;
00709
00710 return 0;
00711 }
00712
00713 return 1;
00714 }
00715
00716
00717 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
00718 {
00719 if(!fd) return 0;
00720 return 0;
00721 }
00722
00723 int FileMPEG::set_audio_position(int64_t sample)
00724 {
00725 #if 0
00726 if(!fd) return 1;
00727
00728 int channel, stream;
00729 to_streamchannel(file->current_channel, stream, channel);
00730
00731
00732 if(sample != mpeg3_get_sample(fd, stream) &&
00733 sample != last_sample)
00734 {
00735 if(sample >= 0 && sample < asset->audio_length)
00736 {
00737
00738 return mpeg3_set_sample(fd, sample, stream);
00739 }
00740 else
00741 return 1;
00742 }
00743 #endif
00744 return 0;
00745 }
00746
00747 int FileMPEG::set_video_position(int64_t x)
00748 {
00749 if(!fd) return 1;
00750 if(x >= 0 && x < asset->video_length)
00751 {
00752 mpeg3_set_frame(fd, x, file->current_layer);
00753 }
00754 else
00755 return 1;
00756 }
00757
00758
00759 int FileMPEG::write_samples(double **buffer, int64_t len)
00760 {
00761 int result = 0;
00762
00763
00764 if(asset->ampeg_derivative == 2)
00765 {
00766
00767 int channels = MIN(asset->channels, 2);
00768 int64_t audio_size = len * channels * 2;
00769 if(toolame_allocation < audio_size)
00770 {
00771 if(toolame_temp) delete [] toolame_temp;
00772 toolame_temp = new unsigned char[audio_size];
00773 toolame_allocation = audio_size;
00774 }
00775
00776 for(int i = 0; i < channels; i++)
00777 {
00778 int16_t *output = ((int16_t*)toolame_temp) + i;
00779 double *input = buffer[i];
00780 for(int j = 0; j < len; j++)
00781 {
00782 int sample = (int)(*input * 0x7fff);
00783 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
00784 output += channels;
00785 input++;
00786 }
00787 }
00788 result = toolame_send_buffer((char*)toolame_temp, audio_size);
00789 }
00790 else
00791 if(asset->ampeg_derivative == 3)
00792 {
00793 int channels = MIN(asset->channels, 2);
00794 int64_t audio_size = len * channels;
00795 if(!lame_global) return 1;
00796 if(!lame_fd) return 1;
00797 if(lame_allocation < audio_size)
00798 {
00799 if(lame_temp[0]) delete [] lame_temp[0];
00800 if(lame_temp[1]) delete [] lame_temp[1];
00801 lame_temp[0] = new float[audio_size];
00802 lame_temp[1] = new float[audio_size];
00803 lame_allocation = audio_size;
00804 }
00805
00806 if(lame_output_allocation < audio_size * 4)
00807 {
00808 if(lame_output) delete [] lame_output;
00809 lame_output_allocation = audio_size * 4;
00810 lame_output = new char[lame_output_allocation];
00811 }
00812
00813 for(int i = 0; i < channels; i++)
00814 {
00815 float *output = lame_temp[i];
00816 double *input = buffer[i];
00817 for(int j = 0; j < len; j++)
00818 {
00819 *output++ = *input++ * (float)32768;
00820 }
00821 }
00822
00823 result = lame_encode_buffer_float(lame_global,
00824 lame_temp[0],
00825 (channels > 1) ? lame_temp[1] : lame_temp[0],
00826 len,
00827 (unsigned char*)lame_output,
00828 lame_output_allocation);
00829 if(result > 0)
00830 {
00831 char *real_output = lame_output;
00832 int bytes = result;
00833 if(!lame_started)
00834 {
00835 for(int i = 0; i < bytes; i++)
00836 if(lame_output[i])
00837 {
00838 real_output = &lame_output[i];
00839 lame_started = 1;
00840 bytes -= i;
00841 break;
00842 }
00843 }
00844 if(bytes > 0 && lame_started)
00845 {
00846 result = !fwrite(real_output, 1, bytes, lame_fd);
00847 if(result)
00848 perror("FileMPEG::write_samples");
00849 }
00850 else
00851 result = 0;
00852 }
00853 else
00854 result = 1;
00855 }
00856
00857 return result;
00858 }
00859
00860 int FileMPEG::write_frames(VFrame ***frames, int len)
00861 {
00862 int result = 0;
00863
00864 if(video_out)
00865 {
00866 int temp_w = (int)((asset->width + 15) / 16) * 16;
00867 int temp_h;
00868
00869
00870 int output_cmodel =
00871 (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
00872
00873
00874
00875 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
00876 temp_h = (int)((asset->height + 15) / 16) * 16;
00877 else
00878 temp_h = (int)((asset->height + 31) / 32) * 32;
00879
00880
00881
00882
00883 for(int i = 0; i < 1; i++)
00884 {
00885 for(int j = 0; j < len && !result; j++)
00886 {
00887 VFrame *frame = frames[i][j];
00888
00889
00890
00891 if(asset->vmpeg_cmodel == MPEG_YUV422)
00892 {
00893 if(frame->get_w() == temp_w &&
00894 frame->get_h() == temp_h &&
00895 frame->get_color_model() == output_cmodel)
00896 {
00897 mpeg2enc_set_input_buffers(0,
00898 (char*)frame->get_y(),
00899 (char*)frame->get_u(),
00900 (char*)frame->get_v());
00901 }
00902 else
00903 {
00904 if(temp_frame &&
00905 (temp_frame->get_w() != temp_w ||
00906 temp_frame->get_h() != temp_h ||
00907 temp_frame->get_color_model() || output_cmodel))
00908 {
00909 delete temp_frame;
00910 temp_frame = 0;
00911 }
00912
00913
00914 if(!temp_frame)
00915 {
00916 temp_frame = new VFrame(0,
00917 temp_w,
00918 temp_h,
00919 output_cmodel);
00920 }
00921
00922 cmodel_transfer(temp_frame->get_rows(),
00923 frame->get_rows(),
00924 temp_frame->get_y(),
00925 temp_frame->get_u(),
00926 temp_frame->get_v(),
00927 frame->get_y(),
00928 frame->get_u(),
00929 frame->get_v(),
00930 0,
00931 0,
00932 asset->width,
00933 asset->height,
00934 0,
00935 0,
00936 asset->width,
00937 asset->height,
00938 frame->get_color_model(),
00939 temp_frame->get_color_model(),
00940 0,
00941 frame->get_w(),
00942 temp_w);
00943
00944 mpeg2enc_set_input_buffers(0,
00945 (char*)temp_frame->get_y(),
00946 (char*)temp_frame->get_u(),
00947 (char*)temp_frame->get_v());
00948 }
00949 }
00950 else
00951 {
00952
00953 if(frame->get_color_model() == output_cmodel)
00954 {
00955 mjpeg_y = frame->get_y();
00956 mjpeg_u = frame->get_u();
00957 mjpeg_v = frame->get_v();
00958 }
00959 else
00960 {
00961 if(!temp_frame)
00962 {
00963 temp_frame = new VFrame(0,
00964 asset->width,
00965 asset->height,
00966 output_cmodel);
00967 }
00968
00969 cmodel_transfer(temp_frame->get_rows(),
00970 frame->get_rows(),
00971 temp_frame->get_y(),
00972 temp_frame->get_u(),
00973 temp_frame->get_v(),
00974 frame->get_y(),
00975 frame->get_u(),
00976 frame->get_v(),
00977 0,
00978 0,
00979 asset->width,
00980 asset->height,
00981 0,
00982 0,
00983 asset->width,
00984 asset->height,
00985 frame->get_color_model(),
00986 temp_frame->get_color_model(),
00987 0,
00988 frame->get_w(),
00989 temp_w);
00990
00991 mjpeg_y = temp_frame->get_y();
00992 mjpeg_u = temp_frame->get_u();
00993 mjpeg_v = temp_frame->get_v();
00994 }
00995
00996
00997
00998
00999 next_frame_lock->unlock();
01000 next_frame_done->lock("FileMPEG::write_frames");
01001 if(mjpeg_error) result = 1;
01002 }
01003
01004
01005
01006
01007
01008 }
01009 }
01010 }
01011
01012
01013
01014 return result;
01015 }
01016
01017 int FileMPEG::read_frame(VFrame *frame)
01018 {
01019 if(!fd) return 1;
01020 int result = 0;
01021 int src_cmodel;
01022
01023 SET_TRACE
01024 if(mpeg3_colormodel(fd, 0) == MPEG3_YUV420P)
01025 src_cmodel = BC_YUV420P;
01026 else
01027 if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
01028 src_cmodel = BC_YUV422P;
01029
01030 SET_TRACE
01031 switch(frame->get_color_model())
01032 {
01033 case MPEG3_RGB565:
01034 case MPEG3_BGR888:
01035 case MPEG3_BGRA8888:
01036 case MPEG3_RGB888:
01037 case MPEG3_RGBA8888:
01038 case MPEG3_RGBA16161616:
01039 mpeg3_read_frame(fd,
01040 frame->get_rows(),
01041 0,
01042 0,
01043 asset->width,
01044 asset->height,
01045 asset->width,
01046 asset->height,
01047 frame->get_color_model(),
01048 file->current_layer);
01049 break;
01050
01051
01052 default:
01053
01054 if(frame->get_color_model() == src_cmodel)
01055 {
01056 mpeg3_read_yuvframe(fd,
01057 (char*)frame->get_y(),
01058 (char*)frame->get_u(),
01059 (char*)frame->get_v(),
01060 0,
01061 0,
01062 asset->width,
01063 asset->height,
01064 file->current_layer);
01065
01066 }
01067 else
01068
01069 {
01070 char *y, *u, *v;
01071 mpeg3_read_yuvframe_ptr(fd,
01072 &y,
01073 &u,
01074 &v,
01075 file->current_layer);
01076 if(y && u && v)
01077 {
01078 cmodel_transfer(frame->get_rows(),
01079 0,
01080 frame->get_y(),
01081 frame->get_u(),
01082 frame->get_v(),
01083 (unsigned char*)y,
01084 (unsigned char*)u,
01085 (unsigned char*)v,
01086 0,
01087 0,
01088 asset->width,
01089 asset->height,
01090 0,
01091 0,
01092 asset->width,
01093 asset->height,
01094 src_cmodel,
01095 frame->get_color_model(),
01096 0,
01097 asset->width,
01098 frame->get_w());
01099 }
01100 }
01101 SET_TRACE
01102 break;
01103 }
01104
01105 return result;
01106 }
01107
01108 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
01109 {
01110 for(stream_out = 0, channel_out = file->current_channel;
01111 stream_out < mpeg3_total_astreams(fd) &&
01112 channel_out >= mpeg3_audio_channels(fd, stream_out);
01113 channel_out -= mpeg3_audio_channels(fd, stream_out), stream_out++)
01114 ;
01115 }
01116
01117 int FileMPEG::read_samples(double *buffer, int64_t len)
01118 {
01119 if(!fd) return 0;
01120
01121
01122 float *temp_float = new float[len];
01123
01124 int stream, channel;
01125 to_streamchannel(file->current_channel, stream, channel);
01126
01127
01128
01129
01130
01131 mpeg3_set_sample(fd,
01132 file->current_sample,
01133 stream);
01134 mpeg3_read_audio(fd,
01135 temp_float,
01136 0,
01137 channel,
01138 len,
01139 stream);
01140
01141
01142
01143 for(int i = 0; i < len; i++) buffer[i] = temp_float[i];
01144
01145 delete [] temp_float;
01146 return 0;
01147 }
01148
01149 int FileMPEG::prefer_samples_float()
01150 {
01151 return 1;
01152 }
01153
01154 int FileMPEG::read_samples_float(float *buffer, int64_t len)
01155 {
01156 if(!fd) return 0;
01157
01158
01159 int stream, channel;
01160 to_streamchannel(file->current_channel, stream, channel);
01161
01162
01163
01164
01165 mpeg3_set_sample(fd,
01166 file->current_sample,
01167 stream);
01168 mpeg3_read_audio(fd,
01169 buffer,
01170 0,
01171 channel,
01172 len,
01173 stream);
01174
01175
01176
01177
01178
01179 return 0;
01180 }
01181
01182
01183
01184 char* FileMPEG::strtocompression(char *string)
01185 {
01186 return "";
01187 }
01188
01189 char* FileMPEG::compressiontostr(char *string)
01190 {
01191 return "";
01192 }
01193
01194
01195
01196
01197
01198
01199
01200 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
01201 : Thread(1, 0, 0)
01202 {
01203 this->file = file;
01204
01205
01206 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
01207 {
01208 mpeg2enc_init_buffers();
01209 mpeg2enc_set_w(file->asset->width);
01210 mpeg2enc_set_h(file->asset->height);
01211 mpeg2enc_set_rate(file->asset->frame_rate);
01212 }
01213 }
01214
01215 FileMPEGVideo::~FileMPEGVideo()
01216 {
01217 Thread::join();
01218 }
01219
01220 void FileMPEGVideo::run()
01221 {
01222 if(file->