Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

filevorbis.C

Go to the documentation of this file.
00001 #include "asset.h"
00002 #include "byteorder.h"
00003 #include "clip.h"
00004 #include "file.h"
00005 #include "filevorbis.h"
00006 #include "guicast.h"
00007 #include "language.h"
00008 #include "mwindow.inc"
00009 
00010 #include <errno.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <unistd.h>
00014 
00015 FileVorbis::FileVorbis(Asset *asset, File *file)
00016  : FileBase(asset, file)
00017 {
00018         reset_parameters();
00019         if(asset->format == FILE_UNKNOWN) asset->format = FILE_VORBIS;
00020         asset->byte_order = 0;
00021 }
00022 
00023 FileVorbis::~FileVorbis()
00024 {
00025         close_file();
00026 }
00027 
00028 void FileVorbis::get_parameters(BC_WindowBase *parent_window, 
00029         Asset *asset, 
00030         BC_WindowBase* &format_window,
00031         int audio_options,
00032         int video_options)
00033 {
00034         if(audio_options)
00035         {
00036                 VorbisConfigAudio *window = new VorbisConfigAudio(parent_window, asset);
00037                 format_window = window;
00038                 window->create_objects();
00039                 window->run_window();
00040                 delete window;
00041         }
00042 }
00043 
00044 int FileVorbis::check_sig(Asset *asset)
00045 {
00046 // FILEVORBIS DECODING IS DISABLED
00047         return 0;
00048         FILE *fd = fopen(asset->path, "rb");
00049         OggVorbis_File vf;
00050 
00051 // Test for Quicktime since OGG misinterprets it
00052         fseek(fd, 4, SEEK_SET);
00053         char data[4];
00054         fread(data, 4, 1, fd);
00055         if(data[0] == 'm' &&
00056                 data[1] == 'd' &&
00057                 data[2] == 'a' &&
00058                 data[3] == 't')
00059         {
00060                 fclose(fd);
00061                 return 0;
00062         }
00063         
00064         fseek(fd, 0, SEEK_SET);
00065 
00066         if(ov_open(fd, &vf, NULL, 0) < 0)
00067         {
00068 // OGG failed.  Close file handle manually.
00069                 ov_clear(&vf);
00070                 if(fd) fclose(fd);
00071                 return 0;
00072         }
00073         else
00074         {
00075                 ov_clear(&vf);
00076                 return 1;
00077         }
00078 }
00079 
00080 int FileVorbis::reset_parameters_derived()
00081 {
00082         fd = 0;
00083         bzero(&vf, sizeof(vf));
00084         pcm_history = 0;
00085         pcm_history_float = 0;
00086 }
00087 
00088 
00089 // Just create the Quicktime objects since this routine is also called
00090 // for reopening.
00091 int FileVorbis::open_file(int rd, int wr)
00092 {
00093         int result = 0;
00094         this->rd = rd;
00095         this->wr = wr;
00096 
00097 //printf("FileVorbis::open_file 1\n");
00098         if(rd)
00099         {
00100 //printf("FileVorbis::open_file 1\n");
00101                 if(!(fd = fopen(asset->path, "rb")))
00102                 {
00103                         printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
00104                         result = 1;
00105                 }
00106                 else
00107                 {
00108 //printf("FileVorbis::open_file 2 %p %p\n", fd, vf);
00109                         if(ov_open(fd, &vf, NULL, 0) < 0)
00110                         {
00111                                 printf(_("FileVorbis::open_file %s: invalid bitstream.\n"), asset->path);
00112                                 result = 1;
00113                         }
00114                         else
00115                         {
00116 //printf("FileVorbis::open_file 1\n");
00117                                 vorbis_info *vi = ov_info(&vf, -1);
00118                                 asset->channels = vi->channels;
00119                                 if(!asset->sample_rate)
00120                                         asset->sample_rate = vi->rate;
00121 //printf("FileVorbis::open_file 1\n");
00122                                 asset->audio_length = ov_pcm_total(&vf,-1);
00123 //printf("FileVorbis::open_file 1\n");
00124                                 asset->audio_data = 1;
00125 // printf("FileVorbis::open_file 1 %d %d %d\n", 
00126 // asset->channels, 
00127 // asset->sample_rate, 
00128 // asset->audio_length);
00129                         }
00130                 }
00131         }
00132 
00133         if(wr)
00134         {
00135                 if(!(fd = fopen(asset->path, "wb")))
00136                 {
00137                         printf("FileVorbis::open_file %s: %s\n", asset->path, strerror(errno));
00138                         result = 1;
00139                 }
00140                 else
00141                 {
00142                         vorbis_info_init(&vi);
00143                         if(!asset->vorbis_vbr)
00144                                 result = vorbis_encode_init(&vi, 
00145                                         asset->channels, 
00146                                         asset->sample_rate, 
00147                                         asset->vorbis_max_bitrate, 
00148                                         asset->vorbis_bitrate, 
00149                                         asset->vorbis_min_bitrate);
00150                         else
00151                         {
00152                                 result = vorbis_encode_setup_managed(&vi,
00153                                         asset->channels, 
00154                                         asset->sample_rate, 
00155                                         asset->vorbis_max_bitrate, 
00156                                         asset->vorbis_bitrate, 
00157                                         asset->vorbis_min_bitrate);
00158                                 result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
00159                                 result |= vorbis_encode_setup_init(&vi);
00160                         }
00161 
00162                         if(!result)
00163                         {
00164                                 vorbis_analysis_init(&vd, &vi);
00165                                 vorbis_block_init(&vd, &vb);
00166                                 vorbis_comment_init(&vc);
00167                                 srand(time(NULL));
00168                                 ogg_stream_init(&os, rand());
00169 
00170                                 ogg_packet header;
00171                                 ogg_packet header_comm;
00172                                 ogg_packet header_code;
00173                                 vorbis_analysis_headerout(&vd, 
00174                                         &vc,
00175                                         &header,
00176                                         &header_comm,
00177                                         &header_code);
00178                                 ogg_stream_packetin(&os,
00179                                         &header);
00180                                 ogg_stream_packetin(&os, 
00181                                         &header_comm);
00182                                 ogg_stream_packetin(&os,
00183                                         &header_code);
00184 
00185                                 while(1)
00186                                 {
00187                                         int result = ogg_stream_flush(&os, &og);
00188                                         if(result == 0) break;
00189                                         fwrite(og.header, 1, og.header_len, fd);
00190                                         fwrite(og.body, 1, og.body_len, fd);
00191                                 }
00192                         }
00193                 }
00194         }
00195 
00196 //printf("FileVorbis::open_file 2\n");
00197         return result;
00198 }
00199 
00200 #define FLUSH_VORBIS \
00201 while(vorbis_analysis_blockout(&vd, &vb) == 1) \
00202 { \
00203         vorbis_analysis(&vb, NULL); \
00204         vorbis_bitrate_addblock(&vb); \
00205         while(vorbis_bitrate_flushpacket(&vd, &op)) \
00206         { \
00207                 ogg_stream_packetin(&os, &op); \
00208                 int done = 0; \
00209                 while(1) \
00210                 { \
00211                         int result = ogg_stream_pageout(&os, &og); \
00212                         if(!result) break; \
00213                         fwrite(og.header, 1, og.header_len, fd); \
00214                         fwrite(og.body, 1, og.body_len, fd); \
00215                         if(ogg_page_eos(&og)) break; \
00216                 } \
00217         } \
00218 }
00219 
00220 
00221 int FileVorbis::close_file()
00222 {
00223         if(fd)
00224         {
00225                 if(wr)
00226                 {
00227                         vorbis_analysis_wrote(&vd, 0);
00228                         FLUSH_VORBIS
00229 
00230                         ogg_stream_clear(&os);
00231                         vorbis_block_clear(&vb);
00232                         vorbis_dsp_clear(&vd);
00233                         vorbis_comment_clear(&vc);
00234                         vorbis_info_clear(&vi);
00235                         fclose(fd);
00236                 }
00237                 
00238                 if(rd)
00239                 {
00240 // This also closes the file handle.
00241                         ov_clear(&vf);
00242                 }
00243                 fd = 0;
00244         }
00245 
00246         if(pcm_history)
00247         {
00248                 for(int i = 0; i < asset->channels; i++)
00249                         delete [] pcm_history[i];
00250                 delete [] pcm_history;
00251         }
00252         if(pcm_history_float)
00253         {
00254                 for(int i = 0; i < asset->channels; i++)
00255                         delete [] pcm_history_float[i];
00256                 delete [] pcm_history_float;
00257         }
00258 
00259         reset_parameters();
00260         FileBase::close_file();
00261         return 0;
00262 }
00263 
00264 
00265 int FileVorbis::write_samples(double **buffer, int64_t len)
00266 {
00267         if(!fd) return 0;
00268         int result = 0;
00269 
00270         float **vorbis_buffer = vorbis_analysis_buffer(&vd, len);
00271         for(int i = 0; i < asset->channels; i++)
00272         {
00273                 float *output = vorbis_buffer[i];
00274                 double *input = buffer[i];
00275                 for(int j = 0; j < len; j++)
00276                 {
00277                         output[j] = input[j];
00278                 }
00279         }
00280     vorbis_analysis_wrote(&vd, len);
00281 
00282         FLUSH_VORBIS
00283 
00284         return result;
00285 }
00286 
00287 int FileVorbis::read_samples(double *buffer, int64_t len)
00288 {
00289         if(!fd) return 0;
00290 
00291 // printf("FileVorbis::read_samples 1 %d %d %d %d\n", 
00292 // history_start, 
00293 // history_size,
00294 // file->current_sample,
00295 // len);
00296         float **vorbis_output;
00297         int bitstream;
00298         int accumulation = 0;
00299 //printf("FileVorbis::read_samples 1\n");
00300         int decode_start = 0;
00301         int decode_len = 0;
00302 
00303         if(len > 0x100000)
00304         {
00305                 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
00306                 return 1;
00307         }
00308 
00309         if(!pcm_history)
00310         {
00311                 pcm_history = new double*[asset->channels];
00312                 for(int i = 0; i < asset->channels; i++)
00313                         pcm_history[i] = new double[HISTORY_MAX];
00314                 history_start = 0;
00315                 history_size = 0;
00316         }
00317 
00318 // Restart history.  Don't bother shifting history back.
00319         if(file->current_sample < history_start ||
00320                 file->current_sample > history_start + history_size)
00321         {
00322                 history_size = 0;
00323                 history_start = file->current_sample;
00324                 decode_start = file->current_sample;
00325                 decode_len = len;
00326         }
00327         else
00328 // Shift history forward to make room for new samples
00329         if(file->current_sample + len > history_start + history_size)
00330         {
00331                 if(file->current_sample + len > history_start + HISTORY_MAX)
00332                 {
00333                         int diff = file->current_sample + len - (history_start + HISTORY_MAX);
00334                         for(int i = 0; i < asset->channels; i++)
00335                         {
00336                                 double *temp = pcm_history[i];
00337                                 for(int j = 0; j < HISTORY_MAX - diff; j++)
00338                                 {
00339                                         temp[j] = temp[j + diff];
00340                                 }
00341                         }
00342                         history_start += diff;
00343                         history_size -= diff;
00344                 }
00345 
00346 // Decode more data
00347                 decode_start = history_start + history_size;
00348                 decode_len = file->current_sample + len - (history_start + history_size);
00349         }
00350 
00351 
00352 // Fill history buffer
00353         if(history_start + history_size != ov_pcm_tell(&vf))
00354         {
00355 //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf));
00356                 ov_pcm_seek(&vf, history_start + history_size);
00357         }
00358 
00359         while(accumulation < decode_len)
00360         {
00361                 int result = ov_read_float(&vf,
00362                         &vorbis_output,
00363                         decode_len - accumulation,
00364                         &bitstream);
00365 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
00366                 if(!result) break;
00367 
00368                 for(int i = 0; i < asset->channels; i++)
00369                 {
00370                         double *output = pcm_history[i] + history_size;
00371                         float *input = vorbis_output[i];
00372                         for(int j = 0; j < result; j++)
00373                                 output[j] = input[j];
00374                 }
00375                 history_size += result;
00376                 accumulation += result;
00377         }
00378 
00379 
00380 // printf("FileVorbis::read_samples 1 %d %d\n", 
00381 // file->current_sample,
00382 // history_start);
00383 
00384         double *input = pcm_history[file->current_channel] + 
00385                 file->current_sample - 
00386                 history_start;
00387         for(int i = 0; i < len; i++)
00388                 buffer[i] = input[i];
00389 
00390 // printf("FileVorbis::read_samples 2 %d %d %d %d\n", 
00391 // history_start, 
00392 // history_size,
00393 // file->current_sample,
00394 // len);
00395 
00396         return 0;
00397 }
00398 
00399 int FileVorbis::prefer_samples_float() 
00400 {
00401         return 1;
00402 }
00403 
00404 int FileVorbis::read_samples_float(float *buffer, int64_t len)
00405 {
00406         if(!fd) return 0;
00407 
00408 // printf("FileVorbis::read_samples 1 %d %d %d %d\n", 
00409 // history_start, 
00410 // history_size,
00411 // file->current_sample,
00412 // len);
00413         float **vorbis_output;
00414         int bitstream;
00415         int accumulation = 0;
00416 //printf("FileVorbis::read_samples 1\n");
00417         int decode_start = 0;
00418         int decode_len = 0;
00419 
00420         if(len > 0x100000)
00421         {
00422                 printf("FileVorbis::read_samples max samples=%d\n", HISTORY_MAX);
00423                 return 1;
00424         }
00425 
00426         if(!pcm_history_float)
00427         {
00428                 pcm_history_float = new float*[asset->channels];
00429                 for(int i = 0; i < asset->channels; i++)
00430                         pcm_history_float[i] = new float[HISTORY_MAX];
00431                 history_start = 0;
00432                 history_size = 0;
00433         }
00434 
00435 // Restart history.  Don't bother shifting history back.
00436         if(file->current_sample < history_start ||
00437                 file->current_sample > history_start + history_size)
00438         {
00439                 history_size = 0;
00440                 history_start = file->current_sample;
00441                 decode_start = file->current_sample;
00442                 decode_len = len;
00443         }
00444         else
00445 // Shift history forward to make room for new samples
00446         if(file->current_sample + len > history_start + history_size)
00447         {
00448                 if(file->current_sample + len > history_start + HISTORY_MAX)
00449                 {
00450                         int diff = file->current_sample + len - (history_start + HISTORY_MAX);
00451                         for(int i = 0; i < asset->channels; i++)
00452                         {
00453                                 float *temp = pcm_history_float[i];
00454 //                              for(int j = 0; j < HISTORY_MAX - diff; j++)
00455 //                              {
00456 //                                      temp[j] = temp[j + diff];
00457 //                              }
00458                                 bcopy(temp, temp + diff, (HISTORY_MAX - diff) * sizeof(float));
00459                         }
00460                         history_start += diff;
00461                         history_size -= diff;
00462                 }
00463 
00464 // Decode more data
00465                 decode_start = history_start + history_size;
00466                 decode_len = file->current_sample + len - (history_start + history_size);
00467         }
00468 
00469 
00470 // Fill history buffer
00471         if(history_start + history_size != ov_pcm_tell(&vf))
00472         {
00473 //printf("FileVorbis::read_samples %d %d\n", history_start + history_size, ov_pcm_tell(&vf));
00474                 ov_pcm_seek(&vf, history_start + history_size);
00475         }
00476 
00477         while(accumulation < decode_len)
00478         {
00479                 int result = ov_read_float(&vf,
00480                         &vorbis_output,
00481                         decode_len - accumulation,
00482                         &bitstream);
00483 //printf("FileVorbis::read_samples 1 %d %d %d\n", result, len, accumulation);
00484                 if(!result) break;
00485 
00486                 for(int i = 0; i < asset->channels; i++)
00487                 {
00488                         float *output = pcm_history_float[i] + history_size;
00489                         float *input = vorbis_output[i];
00490 //                      for(int j = 0; j < result; j++)
00491 //                              output[j] = input[j];
00492                         bcopy(input, output, result * sizeof(float));
00493                 }
00494                 history_size += result;
00495                 accumulation += result;
00496         }
00497 
00498 
00499 // printf("FileVorbis::read_samples 1 %d %d\n", 
00500 // file->current_sample,
00501 // history_start);
00502 
00503         float *input = pcm_history_float[file->current_channel] + 
00504                 file->current_sample - 
00505                 history_start;
00506 //      for(int i = 0; i < len; i++)
00507 //              buffer[i] = input[i];
00508         bcopy(input, buffer, len * sizeof(float));
00509 
00510 // printf("FileVorbis::read_samples 2 %d %d %d %d\n", 
00511 // history_start, 
00512 // history_size,
00513 // file->current_sample,
00514 // len);
00515 
00516         return 0;
00517 }
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 VorbisConfigAudio::VorbisConfigAudio(BC_WindowBase *parent_window, 
00529         Asset *asset)
00530  : BC_Window(PROGRAM_NAME ": Audio Compression",
00531         parent_window->get_abs_cursor_x(1),
00532         parent_window->get_abs_cursor_y(1),
00533         350,
00534         170,
00535         -1,
00536         -1,
00537         0,
00538         0,
00539         1)
00540 {
00541         this->parent_window = parent_window;
00542         this->asset = asset;
00543 }
00544 
00545 VorbisConfigAudio::~VorbisConfigAudio()
00546 {
00547 }
00548 
00549 int VorbisConfigAudio::create_objects()
00550 {
00551         int x = 10, y = 10;
00552         int x1 = 150;
00553         char string[BCTEXTLEN];
00554 
00555         add_tool(fixed_bitrate = new VorbisFixedBitrate(x, y, this));
00556         add_tool(variable_bitrate = new VorbisVariableBitrate(x1, y, this));
00557 
00558         y += 30;
00559         sprintf(string, "%d", asset->vorbis_min_bitrate);
00560         add_tool(new BC_Title(x, y, _("Min bitrate:")));
00561         add_tool(new VorbisMinBitrate(x1, y, this, string));
00562 
00563         y += 30;
00564         add_tool(new BC_Title(x, y, _("Avg bitrate:")));
00565         sprintf(string, "%d", asset->vorbis_bitrate);
00566         add_tool(new VorbisAvgBitrate(x1, y, this, string));
00567 
00568         y += 30;
00569         add_tool(new BC_Title(x, y, _("Max bitrate:")));
00570         sprintf(string, "%d", asset->vorbis_max_bitrate);
00571         add_tool(new VorbisMaxBitrate(x1, y, this, string));
00572 
00573 
00574         add_subwindow(new BC_OKButton(this));
00575         show_window();
00576         flush();
00577         return 0;
00578 }
00579 
00580 int VorbisConfigAudio::close_event()
00581 {
00582         set_done(0);
00583         return 1;
00584 }
00585 
00586 
00587 
00588 
00589 
00590 VorbisFixedBitrate::VorbisFixedBitrate(int x, int y, VorbisConfigAudio *gui)
00591  : BC_Radial(x, y, !gui->asset->vorbis_vbr, _("Fixed bitrate"))
00592 {
00593         this->gui = gui;
00594 }
00595 int VorbisFixedBitrate::handle_event()
00596 {
00597         gui->asset->vorbis_vbr = 0;
00598         gui->variable_bitrate->update(0);
00599         return 1;
00600 }
00601 
00602 VorbisVariableBitrate::VorbisVariableBitrate(int x, int y, VorbisConfigAudio *gui)
00603  : BC_Radial(x, y, gui->asset->vorbis_vbr, _("Variable bitrate"))
00604 {
00605         this->gui = gui;
00606 }
00607 int VorbisVariableBitrate::handle_event()
00608 {
00609         gui->asset->vorbis_vbr = 1;
00610         gui->fixed_bitrate->update(0);
00611         return 1;
00612 }
00613 
00614 
00615 VorbisMinBitrate::VorbisMinBitrate(int x, 
00616         int y, 
00617         VorbisConfigAudio *gui, 
00618         char *text)
00619  : BC_TextBox(x, y, 180, 1, text)
00620 {
00621         this->gui = gui;
00622 }
00623 int VorbisMinBitrate::handle_event()
00624 {
00625         gui->asset->vorbis_min_bitrate = atol(get_text());
00626         return 1;
00627 }
00628 
00629 
00630 
00631 VorbisMaxBitrate::VorbisMaxBitrate(int x, 
00632         int y, 
00633         VorbisConfigAudio *gui,
00634         char *text)
00635  : BC_TextBox(x, y, 180, 1, text)
00636 {
00637         this->gui = gui;
00638 }
00639 int VorbisMaxBitrate::handle_event()
00640 {
00641         gui->asset->vorbis_max_bitrate = atol(get_text());
00642         return 1;
00643 }
00644 
00645 
00646 
00647 VorbisAvgBitrate::VorbisAvgBitrate(int x, int y, VorbisConfigAudio *gui, char *text)
00648  : BC_TextBox(x, y, 180, 1, text)
00649 {
00650         this->gui = gui;
00651 }
00652 int VorbisAvgBitrate::handle_event()
00653 {
00654         gui->asset->vorbis_bitrate = atol(get_text());
00655         return 1;
00656 }
00657 
00658 
00659 
00660 

Generated on Sun Jan 8 13:38:55 2006 for Cinelerra-svn by  doxygen 1.4.4