Audacity  3.0.3
ODDecodeTask.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  ODDecodeTask
6 
7  Created by Michael Chinen (mchinen) on 8/10/08.
8  Audacity(R) is copyright (c) 1999-2008 Audacity Team.
9  License: GPL v2. See License.txt.
10 
11 ******************************************************************//*******************************************************************/
18 
19 #include "../Audacity.h"
20 #include "ODDecodeTask.h"
21 
22 #include "../blockfile/ODDecodeBlockFile.h"
23 #include "../Sequence.h"
24 #include "../WaveClip.h"
25 #include "../WaveTrack.h"
26 #include <wx/wx.h>
27 
30 {
31  mMaxBlockFiles = 0;
32 }
33 
34 
37 {
38  if(mBlockFiles.size()<=0)
39  {
40  mPercentCompleteMutex.Lock();
41  mPercentComplete = 1.0;
42  mPercentCompleteMutex.Unlock();
43  return;
44  }
45 
46  ODFileDecoder* decoder;
47 
48  for(size_t j=0; j < mWaveTracks.size() && mBlockFiles.size();j++)
49  {
50  const auto bf = mBlockFiles[0].lock();
51  sampleCount blockStartSample = 0;
52  sampleCount blockEndSample = 0;
53  bool success =false;
54 
55  int ret = 1;
56 
57  if(bf)
58  {
59  //OD TODO: somehow pass the bf a reference to the decoder that manages its file.
60  //we need to ensure that the filename won't change or be moved. We do this by calling LockRead(),
61  //which the dirmanager::EnsureSafeFilename also does.
62  {
63  auto locker = bf->LockForRead();
64  //Get the decoder. If the file was moved, we need to create another one and init it.
65  decoder = GetOrCreateMatchingFileDecoder( &*bf );
66  if(!decoder->IsInitialized())
67  decoder->Init();
68  bf->SetODFileDecoder(decoder);
69  // Does not throw:
70  ret = bf->DoWriteBlockFile();
71  }
72 
73  if(ret >= 0) {
74  success = true;
75  blockStartSample = bf->GetStart();
76  blockEndSample = blockStartSample + bf->GetLength();
77  }
78  }
79  else
80  {
81  success = true;
82  // The block file disappeared.
83  //the waveform in the wavetrack now is shorter, so we need to update mMaxBlockFiles
84  //because now there is less work to do.
86  }
87 
88  if (success)
89  {
90  //take it out of the array - we are done with it.
91  mBlockFiles.erase(mBlockFiles.begin());
92  }
93  else
94  // The task does not make progress
95  ;
96 
97  //Release the refcount we placed on it if we are successful
98  if( bf && success ) {
99  //upddate the gui for all associated blocks. It doesn't matter that we're hitting more wavetracks then we should
100  //because this loop runs a number of times equal to the number of tracks, they probably are getting processed in
101  //the next iteration at the same sample window.
102  mWaveTrackMutex.Lock();
103  for(size_t i=0;i<mWaveTracks.size();i++)
104  {
105  auto waveTrack = mWaveTracks[i].lock();
106  if(waveTrack)
107  {
108 #if 0 // LLL: Commented out while removing OD files handling
109  waveTrack->AddInvalidRegion(blockStartSample,blockEndSample);
110 #endif
111  }
112  }
113  mWaveTrackMutex.Unlock();
114  }
115  }
116 
117  //update percentage complete.
119 }
120 
122 {
123  mPercentCompleteMutex.Lock();
124  mPercentComplete = (float) 1.0 - ((float)mBlockFiles.size() / (mMaxBlockFiles+1));
125  mPercentCompleteMutex.Unlock();
126 }
127 
129 {
130  for (unsigned int i = 0; i < mDecoders.size(); i++) {
131  if(!mDecoders[i]->SeekingAllowed())
132  return false;
133  }
134  return true;
135 }
136 
139 {
140  std::vector< std::weak_ptr< ODDecodeBlockFile > > tempBlocks;
141 
142  mWaveTrackMutex.Lock();
143 
144  for(size_t j=0;j<mWaveTracks.size();j++)
145  {
146  auto waveTrack = mWaveTracks[j].lock();
147  if(waveTrack)
148  {
149  BlockArray *blocks;
150  Sequence *seq;
151 
152  //gather all the blockfiles that we should process in the wavetrack.
153  for (const auto &clip : waveTrack->GetAllClips()) {
154  seq = clip->GetSequence();
155  //TODO:this lock is way to big since the whole file is one sequence. find a way to break it down.
156  seq->LockDeleteUpdateMutex();
157 
158  //See Sequence::Delete() for why need this for now..
159  blocks = clip->GetSequenceBlockArray();
160  int i;
161  int insertCursor;
162 
163  insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n)
164  for (i = 0; i<(int)blocks->size(); i++)
165  {
166  //since we have more than one ODDecodeBlockFile, we will need type flags to cast.
167  SeqBlock &block = (*blocks)[i];
168  const auto &file = block.f;
169  std::shared_ptr<ODDecodeBlockFile> oddbFile;
170  if (!file->IsDataAvailable() &&
171  (oddbFile =
172  std::static_pointer_cast<ODDecodeBlockFile>(file))->GetDecodeType() == this->GetODType())
173  {
174  oddbFile->SetStart(block.start);
175  oddbFile->SetClipOffset(sampleCount(
176  clip->GetStartTime()*clip->GetRate()
177  ));
178 
179  //these will always be linear within a sequence-lets take advantage of this by keeping a cursor.
180  {
181  std::shared_ptr< ODDecodeBlockFile > ptr;
182  while(insertCursor < (int)tempBlocks.size() &&
183  (!(ptr = tempBlocks[insertCursor].lock()) ||
184  ptr->GetStart() + ptr->GetClipOffset() <
185  oddbFile->GetStart() + oddbFile->GetClipOffset()))
186  insertCursor++;
187  }
188 
189  tempBlocks.insert(tempBlocks.begin() + insertCursor++, oddbFile);
190  }
191  }
192 
193  seq->UnlockDeleteUpdateMutex();
194  }
195  }
196  }
197  mWaveTrackMutex.Unlock();
198 
199  //get the NEW order.
200  OrderBlockFiles(tempBlocks);
201 }
202 
203 
204 
207  (std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks)
208 {
209  mBlockFiles.clear();
210  //TODO:order the blockfiles into our queue in a fancy convenient way. (this could be user-prefs)
211  //for now just put them in linear. We start the order from the first block that includes the ondemand sample
212  //(which the user sets by clicking.) note that this code is pretty hacky - it assumes that the array is sorted in time.
213 
214  //find the startpoint
215  auto processStartSample = GetDemandSample();
216  std::shared_ptr< ODDecodeBlockFile > firstBlock;
217  for(auto i = unorderedBlocks.size(); i--; )
218  {
219  auto ptr = unorderedBlocks[i].lock();
220  if(ptr)
221  {
222  //test if the blockfiles are near the task cursor. we use the last mBlockFiles[0] as our point of reference
223  //and add ones that are closer.
224  //since the order is linear right to left, this will add blocks so that the ones on the right side of the target
225  //are processed first, with the ones closer being processed earlier. Then the ones on the left side get processed.
226  if(mBlockFiles.size() &&
227  ptr->GetGlobalEnd() >= processStartSample &&
228  ( firstBlock->GetGlobalEnd() < processStartSample ||
229  ptr->GetGlobalStart() <= firstBlock->GetGlobalStart()) )
230  {
231  //insert at the front of the list if we get blockfiles that are after the demand sample
232  firstBlock = ptr;
233  mBlockFiles.insert(mBlockFiles.begin(), unorderedBlocks[i]);
234  }
235  else
236  {
237  //otherwise no priority
238  if ( !firstBlock )
239  firstBlock = ptr;
240  mBlockFiles.push_back(unorderedBlocks[i]);
241  }
242  if(mMaxBlockFiles< (int) mBlockFiles.size())
243  mMaxBlockFiles = mBlockFiles.size();
244  }
245  else
246  {
247  // The block file disappeared.
248  }
249  }
250 
251 }
252 
253 
254 
257 void ODDecodeTask::DemandTrackUpdate(WaveTrack* track, double seconds)
258 {
259  //only update if the subclass says we can seek.
260  if(SeekingAllowed())
261  ODTask::DemandTrackUpdate(track,seconds);
262 }
263 
264 
271 {
272  ODFileDecoder* ret=NULL;
273  //see if the filename matches any of our decoders, if so, return it.
274  for(int i=0;i<(int)mDecoders.size();i++)
275  {
276  //we check filename and decode type, since two types of ODDecoders might work with the same filetype
277  //e.g., FFmpeg and LibMad import both do MP3s. TODO: is this necessary? in theory we filter this when
278  //updating our list of blockfiles.
279  if(mDecoders[i]->GetFileName()==blockFile->GetAudioFileName().GetFullPath() &&
280  GetODType() == blockFile->GetDecodeType() )
281  {
282  ret = mDecoders[i].get();
283  break;
284  }
285  }
286 
287  //otherwise, create and add one, and return it.
288  if(!ret)
289  {
290  ret=CreateFileDecoder(blockFile->GetAudioFileName().GetFullPath());
291  }
292  return ret;
293 }
295 {
296  return mDecoders.size();
297 }
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
ODDecodeTask::CreateFileDecoder
virtual ODFileDecoder * CreateFileDecoder(const wxString &fileName)=0
Creates an ODFileDecoder that decodes a file of filetype the subclass handles.
ODTask::DemandTrackUpdate
virtual void DemandTrackUpdate(WaveTrack *track, double seconds)
changes the tasks associated with this Waveform to process the task from a different point in the tra...
Definition: ODTask.cpp:318
ODDecodeTask::CalculatePercentComplete
void CalculatePercentComplete() override
recalculates the percentage complete.
Definition: ODDecodeTask.cpp:121
ODFileDecoder::Init
virtual bool Init()
Definition: ODDecodeBlockFile.h:203
ODDecodeTask::GetNumFileDecoders
virtual int GetNumFileDecoders()
Definition: ODDecodeTask.cpp:294
ODDecodeBlockFile
An AliasBlockFile that references uncompressed data in an existing file.
Definition: ODDecodeBlockFile.h:37
ODDecodeBlockFile::SetStart
void SetStart(sampleCount startSample)
Sets the value that indicates where the first sample in this block corresponds to the global sequence...
Definition: ODDecodeBlockFile.h:97
ODDecodeTask::DoSomeInternal
void DoSomeInternal() override
Computes and writes the data for one BlockFile if it still has a refcount.
Definition: ODDecodeTask.cpp:36
ODDecodeBlockFile::GetGlobalStart
sampleCount GetGlobalStart() const
Definition: ODDecodeBlockFile.h:103
Sequence
A WaveTrack contains WaveClip(s). A WaveClip contains a Sequence. A Sequence is primarily an interfac...
Definition: Sequence.h:61
ODDecodeBlockFile::SetClipOffset
void SetClipOffset(sampleCount numSamples)
sets the amount of samples the clip associated with this blockfile is offset in the wavetrack (non ef...
Definition: ODDecodeBlockFile.h:122
ODTask::mPercentCompleteMutex
ODLock mPercentCompleteMutex
Definition: ODTask.h:152
ODTask::mWaveTracks
std::vector< std::weak_ptr< WaveTrack > > mWaveTracks
Definition: ODTask.h:160
ODFileDecoder::IsInitialized
bool IsInitialized()
Definition: ODDecodeBlockFile.cpp:548
ODTask::mWaveTrackMutex
ODLock mWaveTrackMutex
Definition: ODTask.h:161
ODDecodeTask::mDecoders
std::vector< std::unique_ptr< ODFileDecoder > > mDecoders
Definition: ODDecodeTask.h:92
ODDecodeTask::Update
void Update() override
by default creates the order of the wavetrack to load.
Definition: ODDecodeTask.cpp:138
ODDecodeBlockFile::GetDecodeType
unsigned int GetDecodeType() const
Returns the type of audiofile this blockfile is loaded from.
Definition: ODDecodeBlockFile.h:118
ODDecodeTask::ODDecodeTask
ODDecodeTask()
Creates a NEW task that decodes files.
Definition: ODDecodeTask.cpp:29
ODDecodeTask::OrderBlockFiles
void OrderBlockFiles(std::vector< std::weak_ptr< ODDecodeBlockFile > > &unorderedBlocks)
Orders the input as either On-Demand or default layered order.
Definition: ODDecodeTask.cpp:207
ODDecodeTask::GetOrCreateMatchingFileDecoder
virtual ODFileDecoder * GetOrCreateMatchingFileDecoder(ODDecodeBlockFile *blockFile)
Definition: ODDecodeTask.cpp:270
ODDecodeBlockFile::GetGlobalEnd
sampleCount GetGlobalEnd() const
Definition: ODDecodeBlockFile.h:106
ODDecodeBlockFile::GetStart
sampleCount GetStart() const
Gets the value that indicates where the first sample in this block corresponds to the global sequence...
Definition: ODDecodeBlockFile.h:100
SeqBlock
Data structure containing pointer to a sample block and a start time. Element of a BlockArray.
Definition: Sequence.h:28
ODFileDecoder
class to decode a particular file (one per file). Saves info such as filename and length (after the h...
Definition: ODDecodeBlockFile.h:194
ODDecodeTask::mMaxBlockFiles
int mMaxBlockFiles
Definition: ODDecodeTask.h:94
BlockArray
Definition: Sequence.h:49
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
ODDecodeTask::DemandTrackUpdate
void DemandTrackUpdate(WaveTrack *track, double seconds) override
Definition: ODDecodeTask.cpp:257
ODDecodeTask.h
ODTask::mPercentComplete
volatile float mPercentComplete
Definition: ODTask.h:151
ODTask::GetDemandSample
virtual sampleCount GetDemandSample() const
Definition: ODTask.cpp:221
ODDecodeTask::SeekingAllowed
virtual bool SeekingAllowed()
Definition: ODDecodeTask.cpp:128
ODDecodeBlockFile::GetAudioFileName
const wxFileName & GetAudioFileName()
Definition: ODDecodeBlockFile.h:132
ODDecodeTask::mBlockFiles
std::vector< std::weak_ptr< ODDecodeBlockFile > > mBlockFiles
Definition: ODDecodeTask.h:91
ODDecodeTask::GetODType
unsigned int GetODType() override
Subclasses should override to return respective type.
Definition: ODDecodeTask.h:59
ODDecodeBlockFile::GetClipOffset
sampleCount GetClipOffset() const
Gets the number of samples the clip associated with this blockfile is offset by.
Definition: ODDecodeBlockFile.h:125
SeqBlock::start
sampleCount start
the sample in the global wavetrack that this block starts at.
Definition: Sequence.h:33