Class: QuickTime::Track

Inherits:
Object
  • Object
show all
Defined in:
lib/quicktime/track.rb,
ext/track.c

Overview

see ext/track.c for additional methods

Instance Method Summary collapse

Instance Method Details

#aspect_ratioObject

returns numerical value for aspect ratio. eg. 1.33333 is 4x3



31
32
33
34
35
36
37
38
# File 'lib/quicktime/track.rb', line 31

def aspect_ratio
  pix_num, pix_den = pixel_aspect_ratio
  encoded_size = encoded_pixel_dimensions
  aspect = (encoded_size[:width].to_f / encoded_size[:height].to_f) * (pix_num.to_f / pix_den.to_f)
  return :widescreen if aspect == (16.0/9.0)
  return :fullframe if aspect == (4.0/3.0)
  :other
end

#audio?Boolean

Returns true/false depending on if track is an audio track.

Returns:

  • (Boolean)


16
17
18
# File 'lib/quicktime/track.rb', line 16

def audio?
  media_type == :audio
end

#track_get_audio_channel_countObject



370
371
372
373
374
375
376
377
378
379
380
# File 'ext/track.c', line 370

static VALUE track_get_audio_channel_count(VALUE obj)
{
  AudioChannelLayout *layout = track_get_audio_channel_layout(obj);
  if (layout == NULL) return Qnil;

  UInt32 numChannels = (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) ? layout->mNumberChannelDescriptions : AudioChannelLayoutTag_GetNumberOfChannels(layout->mChannelLayoutTag);
  
  free(layout);
  
  return INT2NUM(numChannels);
}

#track_get_audio_channel_mapArray

Returns an array n-channels in length

Array contains Hashes in the form: {:assignment => :description} where :description is a symbol representing an audio channel description.  eg. :Left, :Right, :Mono

Returns:

  • (Array)


493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# File 'ext/track.c', line 493

static VALUE track_get_audio_channel_map(VALUE obj)
{
  AudioChannelLayout *layout = track_get_audio_channel_layout(obj);
  if (layout == NULL) return Qnil;
  
  VALUE channels = Qnil;
  UInt32 numChannels, x, highLayoutTag;
  VALUE channel;
  char message[256];
  AudioChannelLayoutTag layoutTag = layout->mChannelLayoutTag;
  
  if (layoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
    // using the descriptions
    // not implemented
    numChannels = layout->mNumberChannelDescriptions;
    channels = rb_ary_new2(numChannels);
    
    // loop through all channels, adding assignment descriptions
    AudioChannelDescription desc;
    char *trackStr;
    for (x=0; x < numChannels; x++) {
      desc = layout->mChannelDescriptions[x];
      trackStr = track_str_for_AudioChannelLabel(desc.mChannelLabel);

      if (trackStr != NULL) {
        ADD_CHANNEL(channels, channel, trackStr);

      } else {
         // unsupported audio channel labels
         ADD_CHANNEL(channels, channel, "UnsupportedByRMov");
         sprintf(message, "ChannelLabel unsupported by rmov: %d", desc.mChannelLabel);
         rb_hash_aset(channel, ID2SYM(rb_intern("message")), rb_str_new2(message));
      }
    }
    

  } else {
    numChannels = AudioChannelLayoutTag_GetNumberOfChannels(layoutTag);
    channels = rb_ary_new2(numChannels);

    if (layoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
      // use the bitmap approach
      // not implemented
      //rb_raise(eQuickTime, "Not Implemented: kAudioChannelLayoutTag_UseChannelBitmap in track_get_audio_channel_map");
      for (x=0; x < numChannels; x++) {
        ADD_CHANNEL(channels, channel, "UnsupportedByRMov");
        rb_hash_aset(channel, ID2SYM(rb_intern("message")), rb_str_new2("UseChannelBitmap unsupported by rmov"));
      }



    } else {
      // using a standard LayoutTag
      switch (layoutTag) {

        case kAudioChannelLayoutTag_Mono:
          ADD_CHANNEL(channels, channel, "Mono");
          break;
        
        case kAudioChannelLayoutTag_Stereo:
          ADD_CHANNEL(channels, channel, "Left");
          ADD_CHANNEL(channels, channel, "Right");
          break;
          
        case kAudioChannelLayoutTag_MatrixStereo :
          ADD_CHANNEL(channels, channel, "LeftTotal");
          ADD_CHANNEL(channels, channel, "RightTotal");
          break;

        default:
          // unsupported channels
          highLayoutTag = (layoutTag & 0xff0000) >> 16;
          sprintf(message, "layoutTag unsupported by rmov: (%dL << 16) | %d", highLayoutTag, numChannels);
          for (x=0; x < numChannels; x++) {
            ADD_CHANNEL(channels, channel, "UnsupportedByRMov");
            rb_hash_aset(channel, ID2SYM(rb_intern("message")), rb_str_new2(message));
          }
          //rb_raise(eQuickTime, "Unsupported ChannelLayoutTag in track_get_audio_channel_map: %d", layoutTag);
          break;
      }

    }

  }
  
  free(layout);
  
  return channels;
}

#track_codecObject

Returns the name of the codec. Only valid for video tracks. Others return nil.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'ext/track.c', line 136

static VALUE track_codec(VALUE obj)
{
	ImageDescriptionHandle image_description = track_image_description(obj);
	
	if (image_description == NULL)
    return Qnil;

  UInt8 *codecStr = (*image_description)->name;
  
  VALUE out_str = rb_str_new( (char*)codecStr+1, (UInt8)codecStr[0] );

  DisposeHandle((Handle)image_description);

  return out_str;
}

#deleteObject

Removes the track from its movie and deletes it from memory.



208
209
210
211
212
# File 'ext/track.c', line 208

static VALUE track_delete(VALUE obj)
{
  DisposeMovieTrack(TRACK(obj));
  return Qnil;
}

#disableObject

Disables the track. See enabled? to determine if it’s disabled already.



219
220
221
222
223
# File 'ext/track.c', line 219

static VALUE track_disable(VALUE obj, VALUE boolean)
{
  SetTrackEnabled(TRACK(obj), FALSE);
  return obj;
}

#track_display_pixel_dimensionsObject

returns hash of dimensions => width, :height => height of the encoded pixel dimensions



623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
# File 'ext/track.c', line 623

static VALUE track_display_pixel_dimensions(VALUE obj)
{
  OSErr osErr = noErr;
  ImageDescriptionHandle image_description = track_image_description(obj);
  if (image_description == NULL) goto bail;
  
  SInt32 width, height;
  osErr = ICMImageDescriptionGetProperty(image_description, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_DisplayWidth, sizeof(width), &width, NULL);
  if (osErr != noErr) goto bail;

  osErr = ICMImageDescriptionGetProperty(image_description, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_DisplayHeight, sizeof(height), &height, NULL);
  if (osErr != noErr) goto bail;

  VALUE size_hash = rb_hash_new();

  rb_hash_aset(size_hash, ID2SYM(rb_intern("width")), INT2NUM(width));
  rb_hash_aset(size_hash, ID2SYM(rb_intern("height")), INT2NUM(height));

  DisposeHandle((Handle)image_description);
  return size_hash;

  bail:
    DisposeHandle((Handle)image_description);
    rb_raise(eQuickTime, "Error %d when getting track_display_pixel_dimensions", osErr);
    return Qnil;
}

#durationObject

Returns the length of this track in seconds using raw_duration and time_scale.



6
7
8
# File 'lib/quicktime/track.rb', line 6

def duration
  raw_duration.to_f/time_scale
end

#enableObject

Enables the track. See enabled? to determine if it’s enabled already.



230
231
232
233
234
# File 'ext/track.c', line 230

static VALUE track_enable(VALUE obj, VALUE boolean)
{
  SetTrackEnabled(TRACK(obj), TRUE);
  return obj;
}

#enabled?Boolean

Returns true/false depending on if the track is enabled.

Returns:

  • (Boolean)


241
242
243
244
245
246
247
248
# File 'ext/track.c', line 241

static VALUE track_enabled(VALUE obj, VALUE boolean)
{
  if (GetTrackEnabled(TRACK(obj)) == TRUE) {
    return Qtrue;
  } else {
    return Qfalse;
  }
}

#track_encoded_pixel_dimensionsObject

returns hash of dimensions => width, :height => height of the encoded pixel dimensions



589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
# File 'ext/track.c', line 589

static VALUE track_encoded_pixel_dimensions(VALUE obj)
{
  OSErr osErr = noErr;
  ImageDescriptionHandle image_description = track_image_description(obj);
  if (image_description == NULL) goto bail;
  
  SInt32 width, height;
  osErr = ICMImageDescriptionGetProperty(image_description, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_EncodedWidth, sizeof(width), &width, NULL);
  if (osErr != noErr) goto bail;

  osErr = ICMImageDescriptionGetProperty(image_description, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_EncodedHeight, sizeof(height), &height, NULL);
  if (osErr != noErr) goto bail;

  VALUE size_hash = rb_hash_new();

  rb_hash_aset(size_hash, ID2SYM(rb_intern("width")), INT2NUM(width));
  rb_hash_aset(size_hash, ID2SYM(rb_intern("height")), INT2NUM(height));

  DisposeHandle((Handle)image_description);
  return size_hash;

  bail:
    DisposeHandle((Handle)image_description);
    rb_raise(eQuickTime, "Error %d when getting track_encoded_pixel_dimensions", osErr);
    return Qnil;
}

#frame_countObject

Returns the number of frames in the track.



67
68
69
70
# File 'ext/track.c', line 67

static VALUE track_frame_count(VALUE obj)
{
  return INT2NUM(GetMediaSampleCount(TRACK_MEDIA(obj)));
}

#frame_rateObject

The average frame_rate for this track. May not be exact.



11
12
13
# File 'lib/quicktime/track.rb', line 11

def frame_rate # what about odd frame rates such as 29.97?
  frame_count/duration
end

#track_heightObject

Returns the height of track data. Only valid for video tracks. Others return nil.



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'ext/track.c', line 177

static VALUE track_height(VALUE obj)
{
	ImageDescriptionHandle image_description = track_image_description(obj);
	
	if (image_description == NULL)
    return Qnil;

  short height = (*image_description)->height;
  
  DisposeHandle((Handle)image_description);

  return INT2NUM(height);
}

#idObject

Returns either id number QuickTime uses to reference this track. Usually only used internally.



198
199
200
201
# File 'ext/track.c', line 198

static VALUE track_id(VALUE obj)
{
  return INT2NUM(GetTrackID(TRACK(obj)));
}

#load(movie, index) ⇒ Object

Loads a QuickTime track from a given movie. This is done automatically when calling movie.tracks.



31
32
33
34
35
36
37
38
# File 'ext/track.c', line 31

static VALUE track_load(VALUE obj, VALUE movie_obj, VALUE index_obj)
{
  RTRACK(obj)->track = GetMovieIndTrack(MOVIE(movie_obj), NUM2INT(index_obj));
  if (!RTRACK(obj)->track)
    rb_raise(eQuickTime, "Unable to fetch track for movie at index %d", NUM2INT(index_obj));
  
  return obj;
}

#media_typeObject

Returns either :audio or :video depending on the type of track this is.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'ext/track.c', line 86

static VALUE track_media_type(VALUE obj)
{
  OSType media_type = track_get_media_type(obj);
  
  if (media_type == SoundMediaType) {
    return ID2SYM(rb_intern("audio"));
  } else if (media_type == VideoMediaType) {
    return ID2SYM(rb_intern("video"));
  } else if (media_type == TextMediaType) {
    return ID2SYM(rb_intern("text"));
  } else {
    return Qnil;
  }
}

#new_audio_mediaObject

Creates a new audio media for this track.

Generally this method is not called directly, instead you can make a new audio track using Movie#new_audio_track.



314
315
316
317
318
# File 'ext/track.c', line 314

static VALUE track_new_audio_media(VALUE obj)
{
  NewTrackMedia(TRACK(obj), SoundMediaType, 44100, 0, 0);
  return obj;
}

#new_text_mediaObject

Creates a new text media for this track.

Generally this method is not called directly, instead you can make a new text track using Movie#new_text_track.



328
329
330
331
332
# File 'ext/track.c', line 328

static VALUE track_new_text_media(VALUE obj)
{
  NewTrackMedia(TRACK(obj), TextMediaType, 600, 0, 0);
  return obj;
}

#new_video_mediaObject

Creates a new video media for this track.

Generally this method is not called directly, instead you can make a new video track using Movie#new_video_track.



300
301
302
303
304
# File 'ext/track.c', line 300

static VALUE track_new_video_media(VALUE obj)
{
  NewTrackMedia(TRACK(obj), VideoMediaType, 600, 0, 0);
  return obj;
}

#offsetObject

Returns the offset of the track from the beginning of the movie (in seconds).



276
277
278
279
# File 'ext/track.c', line 276

static VALUE track_get_offset(VALUE obj)
{
  return rb_float_new((double)GetTrackOffset(TRACK(obj))/GetMediaTimeScale(TRACK_MEDIA(obj)));
}

#offset=(seconds) ⇒ Object

Sets the offset of the track from the start of the movie (in seconds).



286
287
288
289
290
# File 'ext/track.c', line 286

static VALUE track_set_offset(VALUE obj, VALUE seconds)
{
  SetTrackOffset(TRACK(obj), TRACK_TIME(obj, seconds));
  return Qnil;
}

#track_pixel_aspect_ratio1

Returns ].

Returns:

  • (1)

    ]



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
# File 'ext/track.c', line 655

static VALUE track_pixel_aspect_ratio(VALUE obj)
{
  OSErr osErr = noErr;
  ImageDescriptionHandle image_description = track_image_description(obj);
  if (image_description == NULL) goto bail;
  
  PixelAspectRatioImageDescriptionExtension dimension;
  osErr = ICMImageDescriptionGetProperty(image_description, kQTPropertyClass_ImageDescription, kICMImageDescriptionPropertyID_PixelAspectRatio, sizeof(dimension), &dimension, NULL);
  if (osErr != noErr) goto bail;
  
//  printf("\naspect ratio: %d:%d\n", dimension.hSpacing, dimension.vSpacing);
  VALUE aspect_ratio = rb_ary_new3(2, INT2NUM(dimension.hSpacing), INT2NUM(dimension.vSpacing));

  DisposeHandle((Handle)image_description);
  return aspect_ratio;

  bail:
    DisposeHandle((Handle)image_description);
    rb_raise(eQuickTime, "Error %d when getting track_encoded_pixel_dimensions", osErr);
    return Qnil;
}

#raw_durationObject

Returns the raw duration of the track. Combine this with time_scale to reach the duration in seconds.



46
47
48
49
# File 'ext/track.c', line 46

static VALUE track_raw_duration(VALUE obj)
{
  return INT2NUM(GetMediaDuration(TRACK_MEDIA(obj)));
}

#text?Boolean

Returns true/false depending on if track is a text track.

Returns:

  • (Boolean)


26
27
28
# File 'lib/quicktime/track.rb', line 26

def text?
  media_type == :text
end

#time_scaleObject

Returns the time scale of the track. Usually only needed when working with raw_duration.



57
58
59
60
# File 'ext/track.c', line 57

static VALUE track_time_scale(VALUE obj)
{
  return INT2NUM(GetMediaTimeScale(TRACK_MEDIA(obj)));
}

#video?Boolean

Returns true/false depending on if track is a video track.

Returns:

  • (Boolean)


21
22
23
# File 'lib/quicktime/track.rb', line 21

def video?
  media_type == :video
end

#volumeObject

Returns the volume of the audio from 0.0 to 1.0.



255
256
257
258
# File 'ext/track.c', line 255

static VALUE track_get_volume(VALUE obj)
{
  return rb_float_new((double)GetTrackVolume(TRACK(obj))/0x0100);
}

#volume=(volume_float) ⇒ Object

Sets the volume to the given value (0.0 to 1.0)



265
266
267
268
269
# File 'ext/track.c', line 265

static VALUE track_set_volume(VALUE obj, VALUE volume_obj)
{
  SetTrackVolume(TRACK(obj), (short)(0x0100*NUM2DBL(volume_obj)));
  return Qnil;
}

#track_widthObject

Returns the width of track data. Only valid for video tracks. Others return nil.



158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'ext/track.c', line 158

static VALUE track_width(VALUE obj)
{
	ImageDescriptionHandle image_description = track_image_description(obj);
	
	if (image_description == NULL)
    return Qnil;

  short width = (*image_description)->width;
  
  DisposeHandle((Handle)image_description);

  return INT2NUM(width);
}