从内存加载影片数据,然后写入影片文件

时间:2015-12-03 19:49:49

标签: macos quicktime

目标:从内存加载电影数据,然后在mac上写入电影文件。

要做到这一点,我发现了这个: https://developer.apple.com/legacy/library/technotes/tn1195/_index.html

我的部分代码是:

void createMovieFromMemory(void *data,
                       Size dataSize,
                       Str255 fileName)
{
    Handle myDataRef = NULL;

    MovieImportComponent    miComponent;
    Track                   targetTrack = nil;
    TimeValue               addedDuration = 0;
    long                    outFlags = 0;
    OSErr                   err;
    ComponentResult         result;
    Movie                   movie = NULL;


    miComponent = OpenDefaultComponent(MovieImportType,kQTFileTypeMP4); //kQTFileTypeWave

    //implementation of this is learned from the link given above
    myDataRef = createPointerDataRefWithExtensions(data, /* pointer to data */
                                                   dataSize, /* size of data */
                                                   fileName, /* file name */
                                                   0, /* file type */
                                                   nil); /* mime type */

    if (myDataRef)
    {
        OSErr err = noErr;
        short id = 0;

        err = MovieImportDataRef(miComponent,
                                 myDataRef,
                                 HandleDataHandlerSubType,
                                 movie,
                                 nil,
                                 &targetTrack,
                                 nil,
                                 &addedDuration,
                                 movieImportCreateTrack,
                                 &outFlags);        


        if (err == noErr)
            DisposeMovie(movie);

        DisposeHandle(myDataRef);
    }
}

现在我的问题是在内存中加载电影的正确方法是什么(用于测试)以及如何在内存中安排电影数据。

目前,我使用以下代码将电影加载到内存:

unsigned int getFileSize(FILE **file){
    unsigned int size;
    if(fseek(*file, 0, SEEK_END) == -1){ return -1; }
    size = ftell(*file);
    fseek(*file, 0, SEEK_SET);
    return size;
}

char *getFileBuffer(FILE **file, unsigned int fileSize){
    char *buffer = malloc(fileSize + 1);
    fread(buffer, fileSize, 1, *file);
    return buffer;
}

unsigned int readFileToMemory(char path[], char **buffer){
unsigned int fileSize;

    FILE *file = fopen(path, "rb");
    if(file != NULL){
        fileSize = getFileSize(&file);
        *buffer = getFileBuffer(&file, fileSize);
        fclose(file);
        return fileSize;
    }else{
        *buffer = NULL;
        return -1;
    }
}

我厌倦了下面的代码:

int main(int argc, const char* argv[])
{

    void* pData = NULL;
    Size iDataSize = 0;
    Str255 strFileName="/Users/x/SAMPLE_convert.mp4";

    char path[] = "/Users/x/SAMPLE.AVI";
    char *buffer;
    int fileSize;
    fileSize = readFileToMemory(path, &buffer);

    iDataSize = fileSize;

    createMovieFromMemory((void*)buffer,iDataSize,strFileName);
    return (0);
}

函数MovieImportDataRef()返回错误代码-50。我搜索周围找不到错误代码-50。欢迎任何建议。谢谢。

JL

1 个答案:

答案 0 :(得分:0)

您使用的是旧版旧API。要打开电影,请使用NewMovieFromProperties():

    CFStringRef path = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8);
    Boolean boolTrue = TRUE;
    QTNewMoviePropertyElement newMovieProperties[] =
    {
        { kQTPropertyClass_DataLocation, kQTDataLocationPropertyID_CFStringNativePath,
            sizeof(CFStringRef), &path, 0 },
        { kQTPropertyClass_NewMovieProperty, kQTNewMoviePropertyID_Active,
            sizeof(boolTrue), &boolTrue, 0 },
        { kQTPropertyClass_MovieInstantiation, kQTMovieInstantiationPropertyID_AsyncOK,
            sizeof(boolTrue), &boolTrue, 0 },
        { kQTPropertyClass_NewMovieProperty, kQTNewMoviePropertyID_DontInteractWithUser,
            sizeof(boolTrue), &boolTrue, 0 },
        { kQTPropertyClass_MovieInstantiation, kQTMovieInstantiationPropertyID_DontAskUnresolvedDataRefs,
            sizeof(boolTrue), &boolTrue, 0 },
    };
    Movie movie = NULL;
    OSStatus err = NewMovieFromProperties(sizeof(newMovieProperties) / sizeof(newMovieProperties[0]), newMovieProperties, 0, NULL, &movie);
    CFRelease(path);
    if (err != noErr)
        fprintf(stderr, "Failed to open movie (error %d)\n", err);

这将从文件中打开电影。您还可以从URL打开电影。你说你想从内存中打开它“用于测试目的”,但这更复杂,因为电影媒体数据可能很大,而QuickTime的设计恰恰不是将它全部加载到内存中,而只是根据需要访问媒体的一部分。如果由于某种原因你确实拥有内存中的数据,最简单的方法可能是先写入文件。

顺便说一下,虽然您没有说出来,但您似乎暗示您想要将电影从一种格式转换为另一种格式(例如AVI到MP4)。 NewMovieFromProperties实际上将从QuickTime支持的任何格式导入媒体文件(包括AVI,MOV,MP4,WAV,3GP,MP3等,不一定只是电影,还包括音频文件,静止图像等)并创建QuickTime电影结构在记忆中。然后,您可以使用任何可用的QuickTime影片导出器组件导出为另一种格式。

-50是参数错误(paramErr),请参阅CarbonCore框架中的MacErrors.h。