用 Media Player 查看 AVI 文件的属性时,看到“内容”页中有“标题”、“艺术家”、“版权”、“分级”等栏目,如何能通过编程的方式修改一个 AVI 文件的这些内容?要用到哪些函数?有没有可以参考的相关资料?望大家不吝赐教,谢谢!

解决方案 »

  1.   

    这个说起来很简单,把AVI文件格式能能够明白了。自然就会了。但要做起来确实得下点功夫。根据某一个文件结合文件格式慢慢修改是一般难度。
    但要,做成适应于各种AVI文件的通用模块就不那么简单了。因为AVI文件的格式不是一成不变的;有时会缺少或增加某些可有可无的CHUNK.得优点耐心。
    最后,说一句,不要依靠MS的AVI函数,他的函数屏蔽了很多宝贵的细节,程序出错都不知道哪的错。
      

  2.   

    楼上说得十分在理,谢谢!我对AVI格式不是很熟悉,但是工作中碰到了这个问题需要解决,希望能得到大家的一些帮助。
    现在我需要修改(或增加)标题、作者、简介信息到一个 AVI 文件中,这个 AVI 文件是由一个 MPEG4 视频流和一个 MP2 音频流组成的,针对这种格式,我该怎么改呢?
      

  3.   

    AVIFile Reference
    This section describes the functions, structures, and macros for applications using the AVIFile services. These elements are grouped as follows:AVIFile Library Operations
    AVIFileInit
    AVIFileExitOpening and Closing AVI Files
    AVIFileOpen
    AVIFileAddRef
    AVIFileRelease
    GetOpenFileNamePreviewReading from a File
    AVIFileInfo
    AVIFILEINFO
    AVIFileReadDataWriting to a File
    AVIFileWriteDataUsing the Clipboard
    AVIPutFileOnClipboard
    AVIGetFromClipboard
    AVIClearClipboardOpening and Closing Streams
    AVIFileGetStream
    AVIStreamOpenFromFile
    AVIStreamAddRef
    AVIStreamReleaseReading Stream Information
    AVISTREAMINFO
    AVIStreamReadData
    AVIStreamDataSize
    AVIStreamReadFormat
    AVIStreamFormatSize
    AVIStreamRead
    AVIStreamSampleSize
    AVIStreamBeginStreaming
    AVIStreamEndStreamingDecompressing Video Data in a Stream
    AVIStreamGetFrameOpen
    AVIStreamGetFrame
    AVIStreamGetFrameCloseCreating a File from Existing Streams
    AVISave
    AVISaveV
    AVISaveOptions
    GetSaveFileNamePreview
    AVIMakeFileFromStreamsWriting Individual Streams
    AVIFileCreateStream
    AVIStreamSetFormat
    AVIStreamWrite
    AVIFileWriteData
    AVIStreamWriteData
    AVIStreamReleaseFinding the Starting Position in a Stream
    AVIStreamStart
    AVIStreamStartTime
    AVIStreamLength
    AVIStreamLengthTime
    AVIStreamFindSample
    AVIStreamEnd
    AVIStreamEndTimeFinding Sample and Key Frames
    AVIStreamFindSample
    AVIStreamIsKeyFrame
    AVIStreamNearestKeyFrame
    AVIStreamNearestKeyFrameTime
    AVIStreamNearestSample
    AVIStreamNearestSampleTime
    AVIStreamNextKeyFrame
    AVIStreamNextKeyFrameTime
    AVIStreamNextSample
    AVIStreamNextSampleTime
    AVIStreamPrevKeyFrame
    AVIStreamPrevKeyFrameTime
    AVIStreamPrevSample
    AVIStreamPrevSampleTime
    AVIStreamSampleToSampleSwitching Between Samples and Time
    AVIStreamSampleToTime
    AVIStreamTimeToSampleCreating Temporary Streams
    AVIStreamCreate
    AVIMakeCompressedStream
    AVIStreamReleaseEditing AVI Streams
    CreateEditableStream
    EditStreamCut
    EditStreamCopy
    EditStreamPaste
    EditStreamClone
    EditStreamSetInfo
    EditStreamSetName
      

  4.   

    谢谢楼上贴出这些函数,这些函数我已经在 MSDN 上查了,感觉似乎只有倒数第二行的那个
    EditStreamSetInfo 函数像是修改 AVI 文件信息的,它在 MSDN 中的描述如下:SDTAPI EditStreamSetInfo(
      PAVISTREAM pavi,         
      AVISTREAMINFO * lpInfo,  
      LONG cbInfo              
    );AVISTREAMINFO 结构的定义为:typedef struct { 
        DWORD fccType; 
        DWORD fccHandler; 
        DWORD dwFlags; 
        DWORD dwCaps; 
        WORD  wPriority; 
        WORD  wLanguage; 
        DWORD dwScale; 
        DWORD dwRate; 
        DWORD dwStart; 
        DWORD dwLength; 
        DWORD dwInitialFrames; 
        DWORD dwSuggestedBufferSize; 
        DWORD dwQuality; 
        DWORD dwSampleSize; 
        RECT  rcFrame; 
        DWORD dwEditCount; 
        DWORD dwFormatChangeCount; 
        char  szName[64]; 
    } AVISTREAMINFO; 不知道这个结构体中的 szName[64] 是不是就是我要修改的地方?
      

  5.   

    楼主,szName[64]并不是你要修改的地方,我十分同意一楼的意见,最好是拿一个现成的已有标题、作者等信息的AVI文件(你指定的那种格式),分析一下他的这些信息所储存的地址,也许可以很好的解决。我看上面一堆的函数里,这二个还是很有可能的,你查一下看:
    AVIFileInfo
    AVIFILEINFO
      

  6.   

    AVIFileInfo
    AVIFILEINFO也不是 :(
      

  7.   

    #include "stdafx.h"
    #include "getframe.h"
    #include "getframeapi.h"
    #include <vfw.h>BOOL ExtractAVIFrames(CString szFileName)
    {
        AVIFileInit();    PAVIFILE avi;
        int res=AVIFileOpen(&avi, szFileName, OF_READ, NULL);    if (res!=AVIERR_OK)
        {
            //an error occures
            if (avi!=NULL)
                AVIFileRelease(avi);
            
            return FALSE;
        }    AVIFILEINFO avi_info;
        AVIFileInfo(avi, &avi_info, sizeof(AVIFILEINFO));    CString szFileInfo;
        szFileInfo.Format("Dimention: %dx%d\n"
                          "Length: %d frames\n"
                          "Max bytes per second: %d\n"
                          "Samples per second: %d\n"
                          "Streams: %d\n"
                          "File Type: %d", avi_info.dwWidth,
                                avi_info.dwHeight,
                                avi_info.dwLength,
                                avi_info.dwMaxBytesPerSec,
                                (DWORD) (avi_info.dwRate / avi_info.dwScale),
                                avi_info.dwStreams,
                                avi_info.szFileType);    AfxMessageBox(szFileInfo, MB_ICONINFORMATION | MB_OK);    PAVISTREAM pStream;
        res=AVIFileGetStream(avi, &pStream, streamtypeVIDEO /*video stream*/, 
                                                   0 /*first stream*/);    if (res!=AVIERR_OK)
        {
            if (pStream!=NULL)
                AVIStreamRelease(pStream);        AVIFileExit();
            return FALSE;
        }    //do some task with the stream
        int iNumFrames;
        int iFirstFrame;    iFirstFrame=AVIStreamStart(pStream);
        if (iFirstFrame==-1)
        {
            //Error getteing the frame inside the stream        if (pStream!=NULL)
                AVIStreamRelease(pStream);        AVIFileExit();
            return FALSE;
        }    iNumFrames=AVIStreamLength(pStream);
        if (iNumFrames==-1)
        {
            //Error getteing the number of frames inside the stream
            
            if (pStream!=NULL)
                AVIStreamRelease(pStream);
            
            AVIFileExit();
            return FALSE;
        }    //getting bitmap from frame
        BITMAPINFOHEADER bih;
        ZeroMemory(&bih, sizeof(BITMAPINFOHEADER));    bih.biBitCount=24;    //24 bit per pixel
        bih.biClrImportant=0;
        bih.biClrUsed = 0;
        bih.biCompression = BI_RGB;
        bih.biPlanes = 1;
        bih.biSize = 40;
        bih.biXPelsPerMeter = 0;
        bih.biYPelsPerMeter = 0;
        //calculate total size of RGBQUAD scanlines (DWORD aligned)
        bih.biSizeImage = (((bih.biWidth * 3) + 3) & 0xFFFC) * bih.biHeight ;    PGETFRAME pFrame;
        pFrame=AVIStreamGetFrameOpen(pStream, 
               NULL/*(BITMAPINFOHEADER*) AVIGETFRAMEF_BESTDISPLAYFMT*/ /*&bih*/);
        
        //Get the first frame
        int index=0;
        for (int i=iFirstFrame; i<iNumFrames; i++)
        {
            index= i-iFirstFrame;        BYTE* pDIB = (BYTE*) AVIStreamGetFrame(pFrame, index);
            
            CreateFromPackedDIBPointer(pDIB, index);
        }    AVIStreamGetFrameClose(pFrame);    //close the stream after finishing the task
        if (pStream!=NULL)
            AVIStreamRelease(pStream);    AVIFileExit();    return TRUE;
    }
    ///The only one function that I must describe more about is: CreateFromPackedDIBPointer(). This function takes a pointer returned from AVIStreamGetFrame() function and creates a bitmap from it. As you know, the AVIStreamGetFrame() returns a pointer to DIB information about the frame. We take this pointer and create a bitmap from it.BOOL CreateFromPackedDIBPointer(LPBYTE pDIB, int iFrame)
    {
        ASSERT(pDIB!=NULL);    //Creates a full-color (no palette) DIB from a pointer to a
        //full-color memory DIB    //get the BitmapInfoHeader
        BITMAPINFOHEADER bih;
        RtlMoveMemory(&bih.biSize, pDIB, sizeof(BITMAPINFOHEADER));    //now get the bitmap bits
        if (bih.biSizeImage < 1)
        {
            return FALSE;
        }    BYTE* Bits=new BYTE[bih.biSizeImage];    RtlMoveMemory(Bits, pDIB + sizeof(BITMAPINFOHEADER), bih.biSizeImage);    //and BitmapInfo variable-length UDT
        BYTE memBitmapInfo[40];
        RtlMoveMemory(memBitmapInfo, &bih, sizeof(bih));    BITMAPFILEHEADER bfh;
        bfh.bfType=19778;    //BM header
        bfh.bfSize=55 + bih.biSizeImage;
        bfh.bfReserved1=0;
        bfh.bfReserved2=0;
        bfh.bfOffBits=sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER); //54
        
        CString FileName;
        FileName.Format("Frame-%05d.bmp", iFrame);
        
        FILE* fp=fopen(FileName, "wb");
        if (fp!=NULL)
        {
            fwrite(&bfh, sizeof(bfh), 1, fp);
            fwrite(&memBitmapInfo, sizeof(memBitmapInfo), 1, fp);
            fwrite(Bits, bih.biSizeImage, 1, fp);
            fclose(fp);
        }
        else
        {
            TRACE0(_T("Error writing the bitmap file"));
            return FALSE;
        }    delete [] Bits;
        return TRUE;
    }