我将使用LibMP4v2库编写一个类来读取MP4文件,但C ++不是我最喜欢的编程语言。
The library contains following structure definitions:
/** Enumeration of possible MP4TagArtwork::type values. */
typedef enum MP4TagArtworkType_e
{
MP4_ART_UNDEFINED = 0,
MP4_ART_BMP = 1,
MP4_ART_GIF = 2,
MP4_ART_JPEG = 3,
MP4_ART_PNG = 4
} MP4TagArtworkType;
/** Data object representing a single piece of artwork. */
typedef struct MP4TagArtwork_s
{
void* data; /**< raw picture data */
uint32_t size; /**< data size in bytes */
MP4TagArtworkType type; /**< data type */
} MP4TagArtwork;
typedef struct MP4TagTrack_s
{
uint16_t index;
uint16_t total;
} MP4TagTrack;
typedef struct MP4TagDisk_s
{
uint16_t index;
uint16_t total;
} MP4TagDisk;
/** Tags <b>convenience</b> structure.
*
* This structure is used in the tags convenience API which allows for
* simplified retrieval and modification of the majority of known tags.
*
* This is a read-only structure and each tag is present if and only if the
* pointer is a <b>non-NULL</b> value. The actual data is backed by a hidden
* data cache which is only updated when the appropriate metadata <b>set</b>
* function is used, or if MP4TagsFetch() is invoked. Thus, if other API
* is used to manipulate relevent atom structure of the MP4 file, the user
* is responsible for re-fetching the data in this structure.
*/
typedef struct MP4Tags_s
{
void* __handle; /* internal use only */
const char* name;
const char* artist;
const char* albumArtist;
const char* album;
const char* grouping;
const char* composer;
const char* comments;
const char* genre;
const uint16_t* genreType;
const char* releaseDate;
const MP4TagTrack* track;
const MP4TagDisk* disk;
const uint16_t* tempo;
const uint8_t* compilation;
const char* tvShow;
const char* tvNetwork;
const char* tvEpisodeID;
const uint32_t* tvSeason;
const uint32_t* tvEpisode;
const char* description;
const char* longDescription;
const char* lyrics;
const char* sortName;
const char* sortArtist;
const char* sortAlbumArtist;
const char* sortAlbum;
const char* sortComposer;
const char* sortTVShow;
const MP4TagArtwork* artwork;
uint32_t artworkCount;
const char* copyright;
const char* encodingTool;
const char* encodedBy;
const char* purchaseDate;
const uint8_t* podcast;
const char* keywords; /* TODO: Needs testing */
const char* category;
const uint8_t* hdVideo;
const uint8_t* mediaType;
const uint8_t* contentRating;
const uint8_t* gapless;
const char* iTunesAccount;
const uint8_t* iTunesAccountType;
const uint32_t* iTunesCountry;
const uint32_t* contentID;
const uint32_t* artistID;
const uint64_t* playlistID;
const uint32_t* genreID;
const uint32_t* composerID;
const char* xid;
} MP4Tags;
我的C#代码是:
[DllImport("libmp4v2.dll", CharSet = CharSet.Ansi)]
private extern static IntPtr MP4Read([MarshalAs(UnmanagedType.LPStr)] string filePath);
[DllImport("libmp4v2.dll", CharSet = CharSet.Ansi)]
private extern static bool MP4TagsFetch(IntPtr tags, IntPtr fileHandle);
[DllImport("libmp4v2.dll", CharSet = CharSet.Ansi)]
private extern static IntPtr MP4TagsAlloc();
[DllImport("libmp4v2.dll", CharSet = CharSet.Ansi)]
private extern static IntPtr MP4FileInfo([MarshalAs(UnmanagedType.LPStr)] string filePath, uint trackId);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MP4TagTrack
{
public ushort Index;
public ushort Total;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MP4TagDisk
{
public ushort Index;
public ushort Total;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CoverArtBox
{
public byte[] data; /**< raw picture data */
public uint size; /**< data size in bytes */
public MP4TagArtworkType type; /**< data type */
}
public enum MP4TagArtworkType
{
MP4_ART_UNDEFINED = 0,
MP4_ART_BMP = 1,
MP4_ART_GIF = 2,
MP4_ART_JPEG = 3,
MP4_ART_PNG = 4
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MP4Tags
{
public string Name;
public string Artist;
public string AlbumArtist;
public string Album;
public string Grouping;
public string Composer;
public string Comments;
public string Genre;
public byte[] GenreType;
public string ReleaseDate;
//public MP4TagTrack Track;
//public MP4TagDisk Disk;
public uint Tempo;
public uint Compilation;
public string TVShow;
public string TVEpisodeID;
public string TVNetwork;
public uint TVSeason;
public uint TVEpisode;
public string SortName;
public string SortArtist;
public string SortAlbumArtist;
public string SortAlbum;
public string SortComposer;
public string SortTVShow;
public string Description;
public string LongDescription;
public string Lyrics;
public CoverArtBox[] Artwork;
public uint ArtworkCount;
public string Copyright;
public string EncodingTool;
public string EncodedBy;
public string PurchaseDate;
public uint Podcast;
public string Keywords;
public string Category;
public uint HDVideo;
public uint MediaType;
public uint ContentRating;
public uint Gapless;
public string iTunesAccount;
public byte iTunesAccountType;
public uint iTunesCountry;
public uint ContentID;
public uint ArtistID;
public ulong PlaylistID;
public uint GenreID;
public uint ComposerID;
public string Xid;
public bool HasMetadata;
}
在调用外部方法MP4TagsFetch并将IntPtr转换为我的结构之后,相同的字段填充了其他字段的数据:
IntPtr fileHandle = MP4Read(FilePath);
IntPtr tags = MP4TagsAlloc();
if (fileHandle != IntPtr.Zero && MP4TagsFetch(tags, fileHandle))
MP4Tags val = (MP4Tags)Marshal.PtrToStructure(tags, typeof(MP4Tags));
出了什么问题?任何人都可以帮助我吗?
答案 0 :(得分:0)
从提供的代码和关闭字段的描述中,我说;这是因为你没有包含句柄的空间。
void* __handle; /* internal use only */
因此,请添加:
public struct MP4Tags
{
public IntPtr Handle; <-----------------------
public string Name;
public string Artist;
public string AlbumArtist;
etc
您应该能够将该字段设为私有以更好地保护它(因为它仅被注释为内部使用),尽管我没有测试它。
<强> EDIT1 强>
我认为这也不正确:
public byte iTunesAccountType;
C声明是这样的:
const uint8_t* iTunesAccountType;
这是一个指针(4个字节假定32位应用程序)。
我实际上用IntPtr字段重新定义你的结构,你认为编组不使用的任何字段,并迭代地将它们重新用于帮助isoltae哪一个是罪魁祸首。 API看起来像是使用指向数据字段的整个指针,因此每个指针都可以用IntPtr替换。