Beispiel #1
0
/* Add the meta data that lavf exposes to the movie */
static void add_metadata(AVFormatContext *ic, Movie theMovie)
{
    QTMetaDataRef movie_metadata;
    OSType err;

    err = QTCopyMovieMetaData(theMovie, &movie_metadata);
    if (err) return;

    void (^AddMetaDataItem)(const char *, OSType) = ^(const char *ff_name, OSType qt_name) {
        AVDictionaryEntry *e = av_dict_get(ic->metadata, ff_name, NULL, 0);
        if (!e) return;

        QTMetaDataAddItem(movie_metadata, kQTMetaDataStorageFormatQuickTime, kQTMetaDataKeyFormatCommon,
                          (UInt8*)&qt_name, sizeof(qt_name), (UInt8*)e->value, strlen(e->value), kQTMetaDataTypeUTF8,
                          NULL);
    };

    AddMetaDataItem("title",     kQTMetaDataCommonKeyDisplayName);
    AddMetaDataItem("author",    kQTMetaDataCommonKeyAuthor);
    AddMetaDataItem("artist",    kQTMetaDataCommonKeyArtist);
    AddMetaDataItem("copyright", kQTMetaDataCommonKeyCopyright);
    AddMetaDataItem("comment",   kQTMetaDataCommonKeyComment);
    AddMetaDataItem("album",     kQTMetaDataCommonKeyAlbum);
    AddMetaDataItem("genre",     kQTMetaDataCommonKeyGenre);
    AddMetaDataItem("composer",  kQTMetaDataCommonKeyComposer);
    AddMetaDataItem("encoder",   kQTMetaDataCommonKeySoftware);
    // TODO iTunes track number, disc number, ...

    QTMetaDataRelease(movie_metadata);
}
Beispiel #2
0
void QTImportFileHandle::AddMetadata(Tags *tags)
{
   QTMetaDataRef metaDataRef = NULL;
   auto cleanup = finally( [&] {
      // we are done so release our metadata object
      if ( metaDataRef )
         QTMetaDataRelease(metaDataRef);
   } );

   OSErr err;

   err = QTCopyMovieMetaData(mMovie, &metaDataRef);
   if (err != noErr) {
      return;
   }

   for (int i = 0; i < WXSIZEOF(names); i++) {
      QTMetaDataItem item = kQTMetaDataItemUninitialized;
      // OSType key = names[i].key;

      err = QTMetaDataGetNextItem(metaDataRef,
                                  kQTMetaDataStorageFormatWildcard,
                                  kQTMetaDataItemUninitialized,
                                  kQTMetaDataKeyFormatCommon,
                                  (const UInt8 *) &names[i].key,
                                  sizeof(names[i].key),
                                  &item);
      if (err != noErr) {
         continue;
      }

      if (item == kQTMetaDataItemUninitialized) {
         continue;
      }

      QTPropertyValueType outPropType;
      ::ByteCount outPropValueSize;
      ::ByteCount outPropValueSizeUsed = 0;
      UInt32 outPropFlags;
      UInt32 dataType;

      // Get data type
      err =  QTMetaDataGetItemProperty(metaDataRef,
                                       item,
                                       kPropertyClass_MetaDataItem,
                                       kQTMetaDataItemPropertyID_DataType,
                                       sizeof(dataType),
                                       &dataType,
                                       &outPropValueSizeUsed);
      if (err != noErr) {
         continue;
      }

      // Get the data length
      err = QTMetaDataGetItemPropertyInfo(metaDataRef,
                                          item,
                                          kPropertyClass_MetaDataItem,
                                          kQTMetaDataItemPropertyID_Value,
                                          &outPropType,
                                          &outPropValueSize,
                                          &outPropFlags );
      if (err != noErr) {
         continue;
      }

      // Alloc memory for it
      ArrayOf<char> outVals{ outPropValueSize };

      // Retrieve the data
      err =  QTMetaDataGetItemProperty(metaDataRef,
                                       item,
                                       kPropertyClass_MetaDataItem,
                                       kQTMetaDataItemPropertyID_Value,
                                       outPropValueSize,
                                       outVals.get(),
                                       &outPropValueSizeUsed);
      if (err != noErr)
         continue;

      wxString v = wxT("");

      switch (dataType)
      {
         case kQTMetaDataTypeUTF8:
            v = wxString(outVals.get(), wxConvUTF8);
         break;
         case kQTMetaDataTypeUTF16BE:
         {
            wxMBConvUTF16BE conv;
            v = wxString(outVals.get(), conv);
         }
         break;
      }

      if (!v.IsEmpty()) {
         tags->SetTag(names[i].name, v);
      }
   }

   return;
}
Beispiel #3
0
void DumpMovieMetaData(Movie theMovie)
{
    require(nil != theMovie, NILMOVIE);

	// get movie metadata reference which is necessary to iterate
	// all the metadata items
	QTMetaDataRef metaDataRef;
	OSStatus status = QTCopyMovieMetaData (theMovie, &metaDataRef );
	require_noerr(status, NOMETADATAREF);
			
	// get count of total number of metadata items for *all* container formats
	ItemCount outCount=0;	
	status = MDUtils_GetStorageFormatCountForAllFormats(metaDataRef, &outCount);
	
	DrawStorageCountStrToWindow("Total for all", outCount);
	DrawStringToFrontWindow(CFSTR("\n"));
	DrawStringToFrontWindow(CFSTR("details:\n"));
	DrawStringToFrontWindow(CFSTR("\n"));

	// display metadata item count values for each of the different storage formats
	ItemCount iTunesShortCount=0, iTunesLongCount=0, UserDataCount=0, QTDataCount=0;	
	status = MDUtils_GetiTunesStorageFormatShortFormCount(metaDataRef, &iTunesShortCount);
	status = MDUtils_GetiTunesStorageFormatLongFormCount(metaDataRef, &iTunesLongCount);
	status = MDUtils_GetUserDataStorageFormatCount(metaDataRef, &UserDataCount);
	status = MDUtils_GetQuickTimeDataStorageFormatCount(metaDataRef, &QTDataCount);

	DrawStorageCountStrToWindow("iTunes ShortForm", iTunesShortCount);
	DrawStorageCountStrToWindow("iTunes LongForm", iTunesLongCount);
	DrawStorageCountStrToWindow("User Data", UserDataCount);
	DrawStorageCountStrToWindow("QuickTime", QTDataCount);

	if (outCount)
	{
		DrawStringToFrontWindow(CFSTR("--------------------------------------------\n"));
		DrawStringToFrontWindow(CFSTR("Key for Metadata Item Display:\n"));
		DrawStringToFrontWindow(CFSTR("\n"));
		DrawStringToFrontWindow(CFSTR("- storage format\n"));
		DrawStringToFrontWindow(CFSTR("- key\n"));
		DrawStringToFrontWindow(CFSTR("- keyformat\n"));
		DrawStringToFrontWindow(CFSTR("- locale\n"));
		DrawStringToFrontWindow(CFSTR("- data type\n"));
		DrawStringToFrontWindow(CFSTR("- value\n"));
	}

	// iterate and display all metadata items

	QTMetaDataItem item = kQTMetaDataItemUninitialized;
	// Get the next metadata item, regardless of the type of storage format
	while (noErr == (MDUtils_GetNextItemForAnyStorageFormat(metaDataRef, item, &item)))
	{
		DrawStringToFrontWindow(CFSTR("--------------------------------------------\n"));
		
		DumpAllPropertiesForMetaDataItem(metaDataRef, item);			
	}

	// we are done so release our metadata object
	QTMetaDataRelease(metaDataRef);
	
NILMOVIE:
NOMETADATAREF:
;

}
Beispiel #4
0
/* Initializes the map & targetTrack to receive audio data */
OSStatus initialize_audio_map(NCStream *map, Track targetTrack, Handle dataRef, OSType dataRefType, AVPacket *firstFrame)
{
    Media media;
    SoundDescriptionHandle sndHdl = NULL;
    AudioStreamBasicDescription asbd;
    AVCodecContext *codec;
    UInt32 ioSize;
    OSStatus err = noErr;

    uint8_t *cookie = NULL;
    size_t cookieSize = 0;

    codec = map->str->codec;
    map->base = map->str->time_base;

    media = NewTrackMedia(targetTrack, SoundMediaType, codec->sample_rate, dataRef, dataRefType);

    map->media = media;

    memset(&asbd,0,sizeof(asbd));
    map_avi_to_mov_tag(codec->codec_id, &asbd, map, codec->channels);
    if(asbd.mFormatID == 0) /* no known codec, use the ms tag */
        asbd.mFormatID = 'ms\0\0' + codec->codec_tag; /* the number is stored in the last byte => big endian */

    /* Ask the AudioToolbox about vbr of the codec */
    ioSize = sizeof(UInt32);
    AudioFormatGetProperty(kAudioFormatProperty_FormatIsVBR, sizeof(AudioStreamBasicDescription), &asbd, &ioSize, &map->vbr);

    cookie = create_cookie(codec, &cookieSize, asbd.mFormatID, map->vbr);
    /* Set as much of the AudioStreamBasicDescription as possible.
     * Then ask the codec to correct it by calling FormatInfo before creating the SoundDescriptionHandle.
     * FormatInfo is poorly documented and doesn't set much of an example for 3rd party codecs but we can hope
     * they'll overwrite bad values here.
     */
    asbd.mSampleRate       = codec->sample_rate;
    asbd.mBytesPerPacket   = codec->block_align;
    asbd.mFramesPerPacket  = codec->frame_size;
    asbd.mChannelsPerFrame = codec->channels;
    asbd.mBitsPerChannel   = codec->bits_per_coded_sample;

    /* ask the toolbox about more information */
    ioSize = sizeof(AudioStreamBasicDescription);
    err = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, cookieSize, cookie, &ioSize, &asbd);

    // We can't recover from this (FormatInfo resets mFormatID for bad MPEG-4 AOTs)
    if (!asbd.mFormatID || !asbd.mChannelsPerFrame) {
        Codecprintf(NULL, "Audio channels or format not set\n");
        goto bail;
    }

    // We might be able to recover from this (at least try to import the packets)
    if (err) {
        Codecprintf(NULL, "AudioFormatGetProperty failed (error %ld / format %lx)\n", err, asbd.mFormatID);
        err = noErr;
    }

    // This needs to be set for playback to work, but 10.4 (+ AppleTV) didn't set it in FormatInfo.
    // FIXME anything non-zero (like 1) might work here
    if (!asbd.mFramesPerPacket && asbd.mFormatID == kAudioFormatMPEGLayer3)
        asbd.mFramesPerPacket = asbd.mSampleRate > 24000 ? 1152 : 576;

    // if we don't have mBytesPerPacket, we can't import as CBR. Probably should be VBR, and the codec
    // either lied about kAudioFormatProperty_FormatIsVBR or isn't present
    if (asbd.mBytesPerPacket == 0)
        map->vbr = 1;

    /* If we have vbr audio, the media scale most likely has to be set to the time_base denumerator */
    if(map->vbr) {
        /* if we have mFramesPerPacket, set mBytesPerPacket to 0 as this can cause
         * errors if set incorrectly. But in vbr, we just need the mFramesPerPacket
         * value */
        if(asbd.mFramesPerPacket)
            asbd.mBytesPerPacket = 0;

        SetMediaTimeScale(media, map->str->time_base.den);
    }

    if (asbd.mFormatID == kAudioFormatLinearPCM)
        asbd.mFramesPerPacket = 1;
    else if (asbd.mBytesPerPacket) {
        /* FIXME: in the MSADPCM codec, we get a wrong mFramesPerPacket entry because
         * of the difference in the sample_rate and the time_base denumerator. So we
         * recalculate here the mFramesPerPacket entry */

        /* For calculation, lets assume a packet duration of 1, use ioSize as tmp storage */
        ioSize = map->str->time_base.num * codec->sample_rate / map->str->time_base.den;
        /* downscale to correct bytes_per_packet */
        asbd.mFramesPerPacket = ioSize * asbd.mBytesPerPacket / codec->block_align;
    }

    AudioChannelLayout acl;
    int aclSize = 0;  //Set this if you intend to use it
    memset(&acl, 0, sizeof(AudioChannelLayout));

    /* We have to parse the format */
    int useDefault = 1;
    if(asbd.mFormatID == kAudioFormatAC3 || asbd.mFormatID == 'ms \0')
    {
        QTMetaDataRef trackMetaData;
        OSStatus error = QTCopyTrackMetaData(targetTrack, &trackMetaData);
        if(error == noErr)
        {
            const char *prop = "Surround";
            OSType key = 'name';
            QTMetaDataAddItem(trackMetaData, kQTMetaDataStorageFormatUserData, kQTMetaDataKeyFormatUserData, (UInt8 *)&key, sizeof(key), (UInt8 *)prop, strlen(prop), kQTMetaDataTypeUTF8, NULL);
            QTMetaDataRelease(trackMetaData);
        }
        if(parse_ac3_bitstream(&asbd, &acl, firstFrame->data, firstFrame->size))
        {
            useDefault = 0;
            aclSize = sizeof(AudioChannelLayout);
        }
    }
    if(useDefault && asbd.mChannelsPerFrame > 2)
    {
        acl = GetDefaultChannelLayout(&asbd);
        aclSize = sizeof(AudioChannelLayout);
    }

    if (asbd.mSampleRate > 0) {
        err = QTSoundDescriptionCreate(&asbd, aclSize == 0 ? NULL : &acl, aclSize, cookie, cookieSize, kQTSoundDescriptionKind_Movie_LowestPossibleVersion, &sndHdl);

        if(err) {
            fprintf(stderr, "AVI IMPORTER: Error %ld creating the sound description\n", err);
            goto bail;
        }
    }
    map->sampleHdl = (SampleDescriptionHandle)sndHdl;
    map->asbd = asbd;

bail:
    if(cookie)
        av_free(cookie);

    return err;
} /* initialize_audio_map() */