OpenShot Library | libopenshot  0.1.1
FrameMapper.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for the FrameMapper class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2014 OpenShot Studios, LLC
9  * <http://www.openshotstudios.com/>. This file is part of
10  * OpenShot Library (libopenshot), an open-source project dedicated to
11  * delivering high quality video editing and animation solutions to the
12  * world. For more information visit <http://www.openshot.org/>.
13  *
14  * OpenShot Library (libopenshot) is free software: you can redistribute it
15  * and/or modify it under the terms of the GNU Lesser General Public License
16  * as published by the Free Software Foundation, either version 3 of the
17  * License, or (at your option) any later version.
18  *
19  * OpenShot Library (libopenshot) is distributed in the hope that it will be
20  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "../include/FrameMapper.h"
29 
30 using namespace std;
31 using namespace openshot;
32 
33 FrameMapper::FrameMapper(ReaderBase *reader, Fraction target, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout) :
34  reader(reader), target(target), pulldown(target_pulldown), final_cache(820 * 1024), is_dirty(true), avr(NULL)
35 {
36  // Set the original frame rate from the reader
37  original = Fraction(reader->info.fps.num, reader->info.fps.den);
38 
39  // Set all info struct members equal to the internal reader
40  info = reader->info;
41  info.fps.num = target.num;
42  info.fps.den = target.den;
43  info.video_timebase.num = target.den;
44  info.video_timebase.den = target.num;
46  info.sample_rate = target_sample_rate;
47  info.channels = target_channels;
48  info.channel_layout = target_channel_layout;
49  info.width = reader->info.width;
50  info.height = reader->info.height;
51 
52  // Used to toggle odd / even fields
53  field_toggle = true;
54 
55  // init mapping between original and target frames
56  Init();
57 }
58 
59 // Destructor
61  if (is_open)
62  // Auto Close if not already
63  Close();
64 }
65 
66 void FrameMapper::AddField(long int frame)
67 {
68  // Add a field, and toggle the odd / even field
69  AddField(Field(frame, field_toggle));
70 }
71 
72 void FrameMapper::AddField(Field field)
73 {
74  // Add a field to the end of the field list
75  fields.push_back(field);
76 
77  // toggle the odd / even flag
78  field_toggle = (field_toggle ? false : true);
79 }
80 
81 // Use the original and target frame rates and a pull-down technique to create
82 // a mapping between the original fields and frames or a video to a new frame rate.
83 // This might repeat or skip fields and frames of the original video, depending on
84 // whether the frame rate is increasing or decreasing.
85 void FrameMapper::Init()
86 {
87  AppendDebugMethod("FrameMapper::Init (Calculate frame mappings)", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
88 
89  // Do not initialize anything if just a picture with no audio
91  // Skip initialization
92  return;
93 
94  // Clear the fields & frames lists
95  fields.clear();
96  frames.clear();
97 
98  // Mark as not dirty
99  is_dirty = false;
100 
101  // Clear cache
102  final_cache.Clear();
103 
104  // Some framerates are handled special, and some use a generic Keyframe curve to
105  // map the framerates. These are the special framerates:
106  if ((original.ToInt() == 24 || original.ToInt() == 25 || original.ToInt() == 30) &&
107  (target.ToInt() == 24 || target.ToInt() == 25 || target.ToInt() == 30)) {
108 
109  // Get the difference (in frames) between the original and target frame rates
110  float difference = target.ToInt() - original.ToInt();
111 
112  // Find the number (i.e. interval) of fields that need to be skipped or repeated
113  int field_interval = 0;
114  int frame_interval = 0;
115 
116  if (difference != 0)
117  {
118  field_interval = round(fabs(original.ToInt() / difference));
119 
120  // Get frame interval (2 fields per frame)
121  frame_interval = field_interval * 2.0f;
122  }
123 
124 
125  // Calculate # of fields to map
126  long int frame = 1;
127  long int number_of_fields = reader->info.video_length * 2;
128 
129  // Loop through all fields in the original video file
130  for (long int field = 1; field <= number_of_fields; field++)
131  {
132 
133  if (difference == 0) // Same frame rate, NO pull-down or special techniques required
134  {
135  // Add fields
136  AddField(frame);
137  }
138  else if (difference > 0) // Need to ADD fake fields & frames, because original video has too few frames
139  {
140  // Add current field
141  AddField(frame);
142 
143  if (pulldown == PULLDOWN_CLASSIC && field % field_interval == 0)
144  {
145  // Add extra field for each 'field interval
146  AddField(frame);
147  }
148  else if (pulldown == PULLDOWN_ADVANCED && field % field_interval == 0 && field % frame_interval != 0)
149  {
150  // Add both extra fields in the middle 'together' (i.e. 2:3:3:2 technique)
151  AddField(frame); // add field for current frame
152 
153  if (frame + 1 <= info.video_length)
154  // add field for next frame (if the next frame exists)
155  AddField(Field(frame + 1, field_toggle));
156  }
157  else if (pulldown == PULLDOWN_NONE && field % frame_interval == 0)
158  {
159  // No pull-down technique needed, just repeat this frame
160  AddField(frame);
161  AddField(frame);
162  }
163  }
164  else if (difference < 0) // Need to SKIP fake fields & frames, because we want to return to the original film frame rate
165  {
166 
167  if (pulldown == PULLDOWN_CLASSIC && field % field_interval == 0)
168  {
169  // skip current field and toggle the odd/even flag
170  field_toggle = (field_toggle ? false : true);
171  }
172  else if (pulldown == PULLDOWN_ADVANCED && field % field_interval == 0 && field % frame_interval != 0)
173  {
174  // skip this field, plus the next field
175  field++;
176  }
177  else if (pulldown == PULLDOWN_NONE && frame % field_interval == 0)
178  {
179  // skip this field, plus the next one
180  field++;
181  }
182  else
183  {
184  // No skipping needed, so add the field
185  AddField(frame);
186  }
187  }
188 
189  // increment frame number (if field is divisible by 2)
190  if (field % 2 == 0 && field > 0)
191  frame++;
192  }
193 
194  } else {
195  // Map the remaining framerates using a simple Keyframe curve
196  // Calculate the difference (to be used as a multiplier)
197  float rate_diff = target.ToFloat() / original.ToFloat();
198  long int new_length = reader->info.video_length * rate_diff;
199 
200  // Build curve for framerate mapping
201  Keyframe rate_curve;
202  rate_curve.AddPoint(1, 1, LINEAR);
203  rate_curve.AddPoint(new_length, reader->info.video_length, LINEAR);
204 
205  // Loop through curve, and build list of frames
206  for (long int frame_num = 1; frame_num <= new_length; frame_num++)
207  {
208  // Add 2 fields per frame
209  AddField(rate_curve.GetInt(frame_num));
210  AddField(rate_curve.GetInt(frame_num));
211  }
212  }
213 
214  // Loop through the target frames again (combining fields into frames)
215  Field Odd(0, true); // temp field used to track the ODD field
216  Field Even(0, true); // temp field used to track the EVEN field
217 
218  // Variables used to remap audio samples
219  int start_samples_frame = 1;
220  int start_samples_position = 0;
221 
222  for (long int field = 1; field <= fields.size(); field++)
223  {
224  // Get the current field
225  Field f = fields[field - 1];
226 
227  // Is field divisible by 2?
228  if (field % 2 == 0 && field > 0)
229  {
230  // New frame number
231  long int frame_number = field / 2;
232 
233  // Set the bottom frame
234  if (f.isOdd)
235  Odd = f;
236  else
237  Even = f;
238 
239  // Determine the range of samples (from the original rate). Resampling happens in real-time when
240  // calling the GetFrame() method. So this method only needs to redistribute the original samples with
241  // the original sample rate.
242  int end_samples_frame = start_samples_frame;
243  int end_samples_position = start_samples_position;
244  int remaining_samples = Frame::GetSamplesPerFrame(frame_number, target, reader->info.sample_rate, reader->info.channels);
245 
246  while (remaining_samples > 0)
247  {
248  // get original samples
249  int original_samples = Frame::GetSamplesPerFrame(end_samples_frame, original, reader->info.sample_rate, reader->info.channels) - end_samples_position;
250 
251  // Enough samples
252  if (original_samples >= remaining_samples)
253  {
254  // Take all that we need, and break loop
255  end_samples_position += remaining_samples;
256  remaining_samples = 0;
257  } else
258  {
259  // Not enough samples (take them all, and keep looping)
260  end_samples_frame += 1; // next frame
261  end_samples_position = 0; // next frame, starting on 1st sample
262  remaining_samples -= original_samples; // reduce the remaining amount
263  }
264  }
265 
266 
267 
268  // Create the sample mapping struct
269  SampleRange Samples = {start_samples_frame, start_samples_position, end_samples_frame, end_samples_position, Frame::GetSamplesPerFrame(frame_number, target, reader->info.sample_rate, reader->info.channels)};
270 
271  // Reset the audio variables
272  start_samples_frame = end_samples_frame;
273  start_samples_position = end_samples_position + 1;
274  if (start_samples_position >= Frame::GetSamplesPerFrame(start_samples_frame, original, reader->info.sample_rate, reader->info.channels))
275  {
276  start_samples_frame += 1; // increment the frame (since we need to wrap onto the next one)
277  start_samples_position = 0; // reset to 0, since we wrapped
278  }
279 
280  // Create a frame and ADD it to the frames collection
281  MappedFrame frame = {Odd, Even, Samples};
282  frames.push_back(frame);
283  }
284  else
285  {
286  // Set the top field
287  if (f.isOdd)
288  Odd = f;
289  else
290  Even = f;
291  }
292  }
293 
294  // Clear the internal fields list (no longer needed)
295  fields.clear();
296 }
297 
298 MappedFrame FrameMapper::GetMappedFrame(long int TargetFrameNumber) throw(OutOfBoundsFrame)
299 {
300  // Ignore mapping on single image readers
301  if (info.has_video and !info.has_audio and info.has_single_image) {
302  // Return the same number
303  MappedFrame frame;
304  frame.Even.Frame = TargetFrameNumber;
305  frame.Odd.Frame = TargetFrameNumber;
306  frame.Samples.frame_start = 0;
307  frame.Samples.frame_end = 0;
308  frame.Samples.sample_start = 0;
309  frame.Samples.sample_end = 0;
310  frame.Samples.total = 0;
311  return frame;
312  }
313 
314  // Check if frame number is valid
315  if(TargetFrameNumber < 1 || frames.size() == 0)
316  // frame too small, return error
317  throw OutOfBoundsFrame("An invalid frame was requested.", TargetFrameNumber, frames.size());
318 
319  else if (TargetFrameNumber > frames.size())
320  // frame too large, set to end frame
321  TargetFrameNumber = frames.size();
322 
323  // Return frame
324  return frames[TargetFrameNumber - 1];
325 }
326 
327 // Get or generate a blank frame
328 tr1::shared_ptr<Frame> FrameMapper::GetOrCreateFrame(long int number)
329 {
330  tr1::shared_ptr<Frame> new_frame;
331 
332  // Init some basic properties about this frame
333  int samples_in_frame = Frame::GetSamplesPerFrame(number, target, info.sample_rate, info.channels);
334 
335  try {
336  // Attempt to get a frame (but this could fail if a reader has just been closed)
337  new_frame = reader->GetFrame(number);
338 
339  // Return real frame
340  return new_frame;
341 
342  } catch (const ReaderClosed & e) {
343  // ...
344  } catch (const TooManySeeks & e) {
345  // ...
346  } catch (const OutOfBoundsFrame & e) {
347  // ...
348  }
349 
350  // Create blank frame
351  new_frame = tr1::shared_ptr<Frame>(new Frame(number, info.width, info.height, "#000000", samples_in_frame, info.channels));
352  new_frame->SampleRate(info.sample_rate);
353  new_frame->ChannelsLayout(info.channel_layout);
354  return new_frame;
355 }
356 
357 // Get an openshot::Frame object for a specific frame number of this reader.
358 tr1::shared_ptr<Frame> FrameMapper::GetFrame(long int requested_frame) throw(ReaderClosed)
359 {
360  // Check final cache, and just return the frame (if it's available)
361  tr1::shared_ptr<Frame> final_frame = final_cache.GetFrame(requested_frame);
362  if (final_frame) return final_frame;
363 
364  // Create a scoped lock, allowing only a single thread to run the following code at one time
365  const GenericScopedLock<CriticalSection> lock(getFrameCriticalSection);
366 
367  // Check if mappings are dirty (and need to be recalculated)
368  if (is_dirty)
369  // Recalculate mappings
370  Init();
371 
372  // Check final cache a 2nd time (due to potential lock already generating this frame)
373  final_frame = final_cache.GetFrame(requested_frame);
374  if (final_frame) return final_frame;
375 
376  // Minimum number of frames to process (for performance reasons)
377  int minimum_frames = OPEN_MP_NUM_PROCESSORS;
378 
379  // Set the number of threads in OpenMP
380  omp_set_num_threads(OPEN_MP_NUM_PROCESSORS);
381  // Allow nested OpenMP sections
382  omp_set_nested(true);
383 
384  #pragma omp parallel
385  {
386  // Debug output
387  AppendDebugMethod("FrameMapper::GetFrame (Loop through frames)", "requested_frame", requested_frame, "minimum_frames", minimum_frames, "", -1, "", -1, "", -1, "", -1);
388 
389  // Loop through all requested frames, each frame gets it's own thread
390  #pragma omp for ordered
391  for (long int frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++)
392  {
393  // Get the mapped frame
394  MappedFrame mapped = GetMappedFrame(frame_number);
395  tr1::shared_ptr<Frame> mapped_frame;
396 
397  #pragma omp ordered
398  mapped_frame = GetOrCreateFrame(mapped.Odd.Frame);
399 
400  // Get # of channels in the actual frame
401  int channels_in_frame = mapped_frame->GetAudioChannelsCount();
402  int samples_in_frame = Frame::GetSamplesPerFrame(frame_number, target, mapped_frame->SampleRate(), channels_in_frame);
403 
404  // Determine if mapped frame is identical to source frame
405  if (info.sample_rate == mapped_frame->SampleRate() &&
406  info.channels == mapped_frame->GetAudioChannelsCount() &&
407  info.channel_layout == mapped_frame->ChannelsLayout() &&
408  info.fps.num == reader->info.fps.num &&
409  info.fps.den == reader->info.fps.den) {
410  // Add original frame to cache, and skip the rest (for performance reasons)
411  final_cache.Add(frame_number, mapped_frame);
412  continue;
413  }
414 
415  // Create a new frame
416  tr1::shared_ptr<Frame> frame = tr1::shared_ptr<Frame>(new Frame(frame_number, 1, 1, "#000000", samples_in_frame, channels_in_frame));
417  frame->SampleRate(mapped_frame->SampleRate());
418  frame->ChannelsLayout(mapped_frame->ChannelsLayout());
419 
420 
421  // Copy the image from the odd field
422  tr1::shared_ptr<Frame> odd_frame;
423  #pragma omp ordered
424  odd_frame = GetOrCreateFrame(mapped.Odd.Frame);
425 
426  if (odd_frame)
427  frame->AddImage(tr1::shared_ptr<QImage>(new QImage(*odd_frame->GetImage())), true);
428  if (mapped.Odd.Frame != mapped.Even.Frame) {
429  // Add even lines (if different than the previous image)
430  tr1::shared_ptr<Frame> even_frame;
431  #pragma omp ordered
432  even_frame = GetOrCreateFrame(mapped.Even.Frame);
433  if (even_frame)
434  frame->AddImage(tr1::shared_ptr<QImage>(new QImage(*even_frame->GetImage())), false);
435  }
436 
437  // Copy the samples
438  int samples_copied = 0;
439  int starting_frame = mapped.Samples.frame_start;
440  while (info.has_audio && samples_copied < mapped.Samples.total)
441  {
442  // Init number of samples to copy this iteration
443  int remaining_samples = mapped.Samples.total - samples_copied;
444  int number_to_copy = 0;
445 
446  // Loop through each channel
447  for (int channel = 0; channel < channels_in_frame; channel++)
448  {
449  // number of original samples on this frame
450  tr1::shared_ptr<Frame> original_frame = GetOrCreateFrame(starting_frame);
451  int original_samples = original_frame->GetAudioSamplesCount();
452 
453  if (starting_frame == mapped.Samples.frame_start)
454  {
455  // Starting frame (take the ending samples)
456  number_to_copy = original_samples - mapped.Samples.sample_start;
457  if (number_to_copy > remaining_samples)
458  number_to_copy = remaining_samples;
459 
460  // Add samples to new frame
461  frame->AddAudio(true, channel, samples_copied, original_frame->GetAudioSamples(channel) + mapped.Samples.sample_start, number_to_copy, 1.0);
462  }
463  else if (starting_frame > mapped.Samples.frame_start && starting_frame < mapped.Samples.frame_end)
464  {
465  // Middle frame (take all samples)
466  number_to_copy = original_samples;
467  if (number_to_copy > remaining_samples)
468  number_to_copy = remaining_samples;
469 
470  // Add samples to new frame
471  frame->AddAudio(true, channel, samples_copied, original_frame->GetAudioSamples(channel), number_to_copy, 1.0);
472  }
473  else
474  {
475  // Ending frame (take the beginning samples)
476  number_to_copy = mapped.Samples.sample_end;
477  if (number_to_copy > remaining_samples)
478  number_to_copy = remaining_samples;
479 
480  // Add samples to new frame
481  frame->AddAudio(false, channel, samples_copied, original_frame->GetAudioSamples(channel), number_to_copy, 1.0);
482  }
483  }
484 
485  // increment frame
486  samples_copied += number_to_copy;
487  starting_frame++;
488  }
489 
490  // Resample audio on frame (if needed)
491  if (info.has_audio &&
492  (info.sample_rate != frame->SampleRate() ||
493  info.channels != frame->GetAudioChannelsCount() ||
494  info.channel_layout != frame->ChannelsLayout()))
495  // Resample audio and correct # of channels if needed
496  ResampleMappedAudio(frame, mapped.Odd.Frame);
497 
498  // Add frame to final cache
499  final_cache.Add(frame->number, frame);
500 
501  } // for loop
502  } // omp parallel
503 
504  // Return processed openshot::Frame
505  return final_cache.GetFrame(requested_frame);
506 }
507 
509 {
510  // Get the difference (in frames) between the original and target frame rates
511  float difference = target.ToInt() - original.ToInt();
512 
513  int field_interval = 0;
514  int frame_interval = 0;
515 
516  if (difference != 0)
517  {
518  // Find the number (i.e. interval) of fields that need to be skipped or repeated
519  field_interval = round(fabs(original.ToInt() / difference));
520 
521  // Get frame interval (2 fields per frame)
522  frame_interval = field_interval * 2.0f;
523  }
524 
525  // Loop through frame mappings
526  for (float map = 1; map <= frames.size(); map++)
527  {
528  MappedFrame frame = frames[map - 1];
529  cout << "Target frame #: " << map << " mapped to original frame #:\t(" << frame.Odd.Frame << " odd, " << frame.Even.Frame << " even)" << endl;
530  cout << " - Audio samples mapped to frame " << frame.Samples.frame_start << ":" << frame.Samples.sample_start << " to frame " << frame.Samples.frame_end << ":" << frame.Samples.sample_end << endl;
531  }
532 
533 }
534 
535 
536 // Determine if reader is open or closed
538  if (reader)
539  return reader->IsOpen();
540  else
541  return false;
542 }
543 
544 
545 // Open the internal reader
547 {
548  if (reader)
549  {
550  AppendDebugMethod("FrameMapper::Open", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
551 
552  // Open the reader
553  reader->Open();
554 
555  // Set child reader in debug mode (if needed)
556  if (debug)
557  reader->debug = true;
558  }
559 }
560 
561 // Close the internal reader
563 {
564  if (reader)
565  {
566  // Create a scoped lock, allowing only a single thread to run the following code at one time
567  const GenericScopedLock<CriticalSection> lock(getFrameCriticalSection);
568 
569  AppendDebugMethod("FrameMapper::Open", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
570 
571  // Close internal reader
572  reader->Close();
573 
574  // Deallocate resample buffer
575  if (avr) {
576  avresample_close(avr);
577  avresample_free(&avr);
578  avr = NULL;
579  }
580  }
581 }
582 
583 
584 // Generate JSON string of this object
586 
587  // Return formatted string
588  return JsonValue().toStyledString();
589 }
590 
591 // Generate Json::JsonValue for this object
592 Json::Value FrameMapper::JsonValue() {
593 
594  // Create root json object
595  Json::Value root = ReaderBase::JsonValue(); // get parent properties
596  root["type"] = "FrameMapper";
597 
598  // return JsonValue
599  return root;
600 }
601 
602 // Load JSON string into this object
603 void FrameMapper::SetJson(string value) throw(InvalidJSON) {
604 
605  // Parse JSON string into JSON objects
606  Json::Value root;
607  Json::Reader reader;
608  bool success = reader.parse( value, root );
609  if (!success)
610  // Raise exception
611  throw InvalidJSON("JSON could not be parsed (or is invalid)", "");
612 
613  try
614  {
615  // Set all values that match
616  SetJsonValue(root);
617  }
618  catch (exception e)
619  {
620  // Error parsing JSON (or missing keys)
621  throw InvalidJSON("JSON is invalid (missing keys or invalid data types)", "");
622  }
623 }
624 
625 // Load Json::JsonValue into this object
626 void FrameMapper::SetJsonValue(Json::Value root) throw(InvalidFile) {
627 
628  // Set parent data
630 
631  // Re-Open path, and re-init everything (if needed)
632  if (reader) {
633 
634  Close();
635  Open();
636  }
637 }
638 
639 // Change frame rate or audio mapping details
640 void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
641 {
642  AppendDebugMethod("FrameMapper::ChangeMapping", "target_fps.num", target_fps.num, "target_fps.den", target_fps.num, "target_pulldown", target_pulldown, "target_sample_rate", target_sample_rate, "target_channels", target_channels, "target_channel_layout", target_channel_layout);
643 
644  // Mark as dirty
645  is_dirty = true;
646 
647  // Update mapping details
648  target = target_fps;
649  pulldown = target_pulldown;
650  info.sample_rate = target_sample_rate;
651  info.channels = target_channels;
652  info.channel_layout = target_channel_layout;
653 
654  // Clear cache
655  final_cache.Clear();
656 
657  // Deallocate resample buffer
658  if (avr) {
659  avresample_close(avr);
660  avresample_free(&avr);
661  avr = NULL;
662  }
663 }
664 
665 // Resample audio and map channels (if needed)
666 void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame, long int original_frame_number)
667 {
668  // Init audio buffers / variables
669  int total_frame_samples = 0;
670  int channels_in_frame = frame->GetAudioChannelsCount();
671  int sample_rate_in_frame = frame->SampleRate();
672  int samples_in_frame = frame->GetAudioSamplesCount();
673  ChannelLayout channel_layout_in_frame = frame->ChannelsLayout();
674 
675  AppendDebugMethod("FrameMapper::ResampleMappedAudio", "frame->number", frame->number, "original_frame_number", original_frame_number, "channels_in_frame", channels_in_frame, "samples_in_frame", samples_in_frame, "sample_rate_in_frame", sample_rate_in_frame, "", -1);
676 
677  // Get audio sample array
678  float* frame_samples_float = NULL;
679  // Get samples interleaved together (c1 c2 c1 c2 c1 c2)
680  frame_samples_float = frame->GetInterleavedAudioSamples(sample_rate_in_frame, NULL, &samples_in_frame);
681 
682  // Calculate total samples
683  total_frame_samples = samples_in_frame * channels_in_frame;
684 
685  // Create a new array (to hold all S16 audio samples for the current queued frames)
686  int16_t* frame_samples = new int16_t[total_frame_samples];
687 
688  // Translate audio sample values back to 16 bit integers
689  for (int s = 0; s < total_frame_samples; s++)
690  // Translate sample value and copy into buffer
691  frame_samples[s] = int(frame_samples_float[s] * (1 << 15));
692 
693 
694  // Deallocate float array
695  delete[] frame_samples_float;
696  frame_samples_float = NULL;
697 
698  AppendDebugMethod("FrameMapper::ResampleMappedAudio (got sample data from frame)", "frame->number", frame->number, "total_frame_samples", total_frame_samples, "target channels", info.channels, "channels_in_frame", channels_in_frame, "target sample_rate", info.sample_rate, "samples_in_frame", samples_in_frame);
699 
700 
701  // Create input frame (and allocate arrays)
702  AVFrame *audio_frame = AV_ALLOCATE_FRAME();
703  AV_RESET_FRAME(audio_frame);
704  audio_frame->nb_samples = total_frame_samples / channels_in_frame;
705 
706  int error_code = avcodec_fill_audio_frame(audio_frame, channels_in_frame, AV_SAMPLE_FMT_S16, (uint8_t *) frame_samples,
707  audio_frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * channels_in_frame, 1);
708 
709  if (error_code < 0)
710  {
711  AppendDebugMethod("FrameMapper::ResampleMappedAudio ERROR [" + (string)av_err2str(error_code) + "]", "error_code", error_code, "", -1, "", -1, "", -1, "", -1, "", -1);
712  throw ErrorEncodingVideo("Error while resampling audio in frame mapper", frame->number);
713  }
714 
715  // Update total samples & input frame size (due to bigger or smaller data types)
716  total_frame_samples = Frame::GetSamplesPerFrame(frame->number, target, info.sample_rate, info.channels);
717 
718  AppendDebugMethod("FrameMapper::ResampleMappedAudio (adjust # of samples)", "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "sample_rate_in_frame", sample_rate_in_frame, "info.channels", info.channels, "channels_in_frame", channels_in_frame, "original_frame_number", original_frame_number);
719 
720  // Create output frame (and allocate arrays)
721  AVFrame *audio_converted = AV_ALLOCATE_FRAME();
722  AV_RESET_FRAME(audio_converted);
723  audio_converted->nb_samples = total_frame_samples;
724  av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, total_frame_samples, AV_SAMPLE_FMT_S16, 0);
725 
726  AppendDebugMethod("FrameMapper::ResampleMappedAudio (preparing for resample)", "in_sample_fmt", AV_SAMPLE_FMT_S16, "out_sample_fmt", AV_SAMPLE_FMT_S16, "in_sample_rate", sample_rate_in_frame, "out_sample_rate", info.sample_rate, "in_channels", channels_in_frame, "out_channels", info.channels);
727 
728  int nb_samples = 0;
729  // Force the audio resampling to happen in order (1st thread to last thread), so the waveform
730  // is smooth and continuous.
731  #pragma omp ordered
732  {
733  // setup resample context
734  if (!avr) {
735  avr = avresample_alloc_context();
736  av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
737  av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
738  av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
739  av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
740  av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
741  av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
742  av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
743  av_opt_set_int(avr, "out_channels", info.channels, 0);
744  avresample_open(avr);
745  }
746 
747  // Convert audio samples
748  nb_samples = avresample_convert(avr, // audio resample context
749  audio_converted->data, // output data pointers
750  audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown)
751  audio_converted->nb_samples, // maximum number of samples that the output buffer can hold
752  audio_frame->data, // input data pointers
753  audio_frame->linesize[0], // input plane size, in bytes (0 if unknown)
754  audio_frame->nb_samples); // number of input samples to convert
755  }
756 
757  // Create a new array (to hold all resampled S16 audio samples)
758  int16_t* resampled_samples = new int16_t[(nb_samples * info.channels)];
759 
760  // Copy audio samples over original samples
761  memcpy(resampled_samples, audio_converted->data[0], (nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels));
762 
763  // Free frames
764  free(audio_frame->data[0]); // TODO: Determine why av_free crashes on Windows
765  AV_FREE_FRAME(&audio_frame);
766  av_free(audio_converted->data[0]);
767  AV_FREE_FRAME(&audio_converted);
768  frame_samples = NULL;
769 
770  // Resize the frame to hold the right # of channels and samples
771  int channel_buffer_size = nb_samples;
772  frame->ResizeAudio(info.channels, channel_buffer_size, info.sample_rate, info.channel_layout);
773 
774  AppendDebugMethod("FrameMapper::ResampleMappedAudio (Audio successfully resampled)", "nb_samples", nb_samples, "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "channels_in_frame", channels_in_frame, "info.channels", info.channels, "info.channel_layout", info.channel_layout);
775 
776  // Array of floats (to hold samples for each channel)
777  float *channel_buffer = new float[channel_buffer_size];
778 
779  // Divide audio into channels. Loop through each channel
780  for (int channel_filter = 0; channel_filter < info.channels; channel_filter++)
781  {
782  // Init array
783  for (int z = 0; z < channel_buffer_size; z++)
784  channel_buffer[z] = 0.0f;
785 
786  // Loop through all samples and add them to our Frame based on channel.
787  // Toggle through each channel number, since channel data is stored like (left right left right)
788  int channel = 0;
789  int position = 0;
790  for (int sample = 0; sample < (nb_samples * info.channels); sample++)
791  {
792  // Only add samples for current channel
793  if (channel_filter == channel)
794  {
795  // Add sample (convert from (-32768 to 32768) to (-1.0 to 1.0))
796  channel_buffer[position] = resampled_samples[sample] * (1.0f / (1 << 15));
797 
798  // Increment audio position
799  position++;
800  }
801 
802  // increment channel (if needed)
803  if ((channel + 1) < info.channels)
804  // move to next channel
805  channel ++;
806  else
807  // reset channel
808  channel = 0;
809  }
810 
811  // Add samples to frame for this channel
812  frame->AddAudio(true, channel_filter, 0, channel_buffer, position, 1.0f);
813 
814  AppendDebugMethod("FrameMapper::ResampleMappedAudio (Add audio to channel)", "number of samples", position, "channel_filter", channel_filter, "", -1, "", -1, "", -1, "", -1);
815  }
816 
817  // Update frame's audio meta data
818  frame->SampleRate(info.sample_rate);
819  frame->ChannelsLayout(info.channel_layout);
820 
821  // clear channel buffer
822  delete[] channel_buffer;
823  channel_buffer = NULL;
824 
825  // Delete arrays
826  delete[] resampled_samples;
827  resampled_samples = NULL;
828 }
#define AV_RESET_FRAME(av_frame)
Classic 2:3:2:3 pull-down.
Definition: FrameMapper.h:62
#define AV_FREE_FRAME(av_frame)
int num
Numerator for the fraction.
Definition: Fraction.h:44
CriticalSection getFrameCriticalSection
Section lock for multiple threads.
Definition: ReaderBase.h:99
vector< MappedFrame > frames
Definition: FrameMapper.h:167
ChannelLayout channel_layout
The channel layout (mono, stereo, 5 point surround, etc...)
Definition: ReaderBase.h:83
int width
The width of the video (in pixesl)
Definition: ReaderBase.h:67
tr1::shared_ptr< Frame > GetFrame(long int requested_frame)
This method is required for all derived classes of ReaderBase, and return the openshot::Frame object...
This class represents a single frame of video (i.e. image & audio data)
Definition: Frame.h:114
void ResampleMappedAudio(tr1::shared_ptr< Frame > frame, long int original_frame_number)
Resample audio and map channels (if needed)
float ToFloat()
Return this fraction as a float (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:41
~FrameMapper()
Destructor.
Definition: FrameMapper.cpp:60
float duration
Length of time (in seconds)
Definition: ReaderBase.h:64
void Close()
Close the openshot::FrameMapper and internal reader.
virtual void Close()=0
Close the reader (and any resources it was consuming)
This abstract class is the base class, used by all readers in libopenshot.
Definition: ReaderBase.h:95
#define OPEN_MP_NUM_PROCESSORS
Exception when a reader is closed, and a frame is requested.
Definition: Exceptions.h:234
bool has_video
Determines if this file has a video stream.
Definition: ReaderBase.h:61
This struct holds a single field (half a frame).
Definition: FrameMapper.h:73
Exception when encoding audio packet.
Definition: Exceptions.h:101
void AddPoint(Point p)
Add a new point on the key-frame. Each point has a primary coordinate, a left handle, and a right handle.
Definition: KeyFrame.cpp:72
This struct holds a the range of samples needed by this frame.
Definition: FrameMapper.h:93
MappedFrame GetMappedFrame(long int TargetFrameNumber)
Get a frame based on the target frame rate and the new frame number of a frame.
bool has_audio
Determines if this file has an audio stream.
Definition: ReaderBase.h:62
void AppendDebugMethod(string method_name, string arg1_name, float arg1_value, string arg2_name, float arg2_value, string arg3_name, float arg3_value, string arg4_name, float arg4_value, string arg5_name, float arg5_value, string arg6_name, float arg6_value)
Append debug information as JSON.
Definition: ReaderBase.cpp:67
void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
Change frame rate or audio mapping details.
int height
The height of the video (in pixels)
Definition: ReaderBase.h:66
#define AV_ALLOCATE_FRAME()
Exception for files that can not be found or opened.
Definition: Exceptions.h:132
bool IsOpen()
Determine if reader is open or closed.
long int Frame
Definition: FrameMapper.h:75
This class represents a fraction.
Definition: Fraction.h:42
bool has_single_image
Determines if this file only contains a single image.
Definition: ReaderBase.h:63
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
Definition: ReaderBase.cpp:153
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
Definition: ReaderBase.cpp:202
#define av_err2str(errnum)
ReaderInfo info
Information about the current media file.
Definition: ReaderBase.h:120
int ToInt()
Return a rounded integer of the fraction (for example 30000/1001 returns 30)
Definition: Fraction.cpp:51
This struct holds two fields which together make up a complete video frame.
Definition: FrameMapper.h:110
Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)
Definition: ReaderBase.h:69
vector< Field > fields
Definition: FrameMapper.h:166
Fraction video_timebase
The video timebase determines how long each frame stays on the screen.
Definition: ReaderBase.h:76
string Json()
Get and Set JSON methods.
Exception for frames that are out of bounds.
Definition: Exceptions.h:202
int GetInt(long int index)
Get the rounded INT value at a specific index.
Definition: KeyFrame.cpp:246
void Clear()
Clear the cache of all frames.
Definition: Cache.cpp:202
virtual tr1::shared_ptr< Frame > GetFrame(long int number)=0
Do not apply pull-down techniques, just repeat or skip entire frames.
Definition: FrameMapper.h:64
Linear curves are angular, straight lines between two points.
Definition: Point.h:47
void PrintMapping()
Print all of the original frames and which new frames they map to.
Exception for invalid JSON.
Definition: Exceptions.h:152
PulldownType
This enumeration determines how frame rates are increased or decreased.
Definition: FrameMapper.h:60
int den
Denominator for the fraction.
Definition: Fraction.h:45
int channels
The number of audio channels used in the audio stream.
Definition: ReaderBase.h:82
A Keyframe is a collection of Point instances, which is used to vary a number or property over time...
Definition: KeyFrame.h:64
long int video_length
The number of frames in the video stream.
Definition: ReaderBase.h:74
int GetSamplesPerFrame(Fraction fps, int sample_rate, int channels)
Calculate the # of samples per video frame (for the current frame number)
Definition: Frame.cpp:482
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Advanced 2:3:3:2 pull-down (minimal dirty frames)
Definition: FrameMapper.h:63
void SetJson(string value)
Load JSON string into this object.
void Open()
Open the internal reader.
double ToDouble()
Return this fraction as a double (i.e. 1/2 = 0.5)
Definition: Fraction.cpp:46
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
int sample_rate
The number of audio samples per second (44100 is a common sample rate)
Definition: ReaderBase.h:81
Exception when too many seek attempts happen.
Definition: Exceptions.h:254
virtual bool IsOpen()=0
A thread safe version of GetFrame.