示例#1
0
    bool Init(CTSTR lpFile)
    {
        strFile = lpFile;
        initialTimestamp = -1;

        if(!fileOut.Open(lpFile, XFILE_CREATEALWAYS, 1024*1024))
            return false;

        fileOut.OutputByte('F');
        fileOut.OutputByte('L');
        fileOut.OutputByte('V');
        fileOut.OutputByte(1);
        fileOut.OutputByte(5); //bit 0 = (hasAudio), bit 2 = (hasAudio)
        fileOut.OutputDword(DWORD_BE(9));
        fileOut.OutputDword(0);

        metaDataPos = fileOut.GetPos();

        char  metaDataBuffer[2048];
        char *enc = metaDataBuffer;
        char *pend = metaDataBuffer+sizeof(metaDataBuffer);

        enc = AMF_EncodeString(enc, pend, &av_onMetaData);
        char *endMetaData  = App->EncMetaData(enc, pend, true);
        UINT  metaDataSize = endMetaData-metaDataBuffer;

        AppendFLVPacket((LPBYTE)metaDataBuffer, metaDataSize, 18, 0);
        return true;
    }
示例#2
0
    ~MP4FileStream()
    {
        if(!bStreamOpened)
            return;

        App->EnableSceneSwitching(false);

        //---------------------------------------------------

        //HWND hwndProgressDialog = CreateDialog(hinstMain, MAKEINTRESOURCE(IDD_BUILDINGMP4), hwndMain, (DLGPROC)MP4ProgressDialogProc);
        //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETRANGE32, 0, 100);

        mdatStop = fileOut.GetPos();

        BufferOutputSerializer output(endBuffer);

        //set a reasonable initial buffer size
        endBuffer.SetSize((videoFrames.Num() + audioFrames.Num()) * 20 + 131072);

        UINT64 audioFrameSize = App->GetAudioEncoder()->GetFrameSize();

        DWORD macTime = fastHtonl(DWORD(GetMacTime()));
        UINT videoDuration = fastHtonl(lastVideoTimestamp + App->GetFrameTime());
        UINT audioDuration = fastHtonl(lastVideoTimestamp + DWORD(double(audioFrameSize)*1000.0/double(App->GetSampleRateHz())));
        UINT width, height;
        App->GetOutputSize(width, height);

        LPCSTR lpVideoTrack = "Video Media Handler";
        LPCSTR lpAudioTrack = "Sound Media Handler";

        const char videoCompressionName[31] = "AVC Coding";

        //-------------------------------------------
        // get video headers
        DataPacket videoHeaders;
        App->GetVideoHeaders(videoHeaders);
        List<BYTE> SPS, PPS;

        LPBYTE lpHeaderData = videoHeaders.lpPacket+11;
        SPS.CopyArray(lpHeaderData+2, fastHtons(*(WORD*)lpHeaderData));

        lpHeaderData += SPS.Num()+3;
        PPS.CopyArray(lpHeaderData+2, fastHtons(*(WORD*)lpHeaderData));

        //-------------------------------------------
        // get AAC headers if using AAC
        List<BYTE> AACHeader;
        if(!bMP3)
        {
            DataPacket data;
            App->GetAudioHeaders(data);
            AACHeader.CopyArray(data.lpPacket+2, data.size-2);
        }

        //-------------------------------------------

        EndChunkInfo(videoChunks, videoSampleToChunk, curVideoChunkOffset, numVideoSamples);
        EndChunkInfo(audioChunks, audioSampleToChunk, curAudioChunkOffset, numAudioSamples);

        if (numVideoSamples > 1)
            GetVideoDecodeTime(videoFrames.Last(), true);

        if (numAudioSamples > 1)
            GetAudioDecodeTime(audioFrames.Last(), true);

        UINT audioUnitDuration = fastHtonl(UINT(lastAudioTimeVal));

        //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 25, 0);

        //-------------------------------------------
        // sound descriptor thingy.  this part made me die a little inside admittedly.
        UINT maxBitRate = fastHtonl(App->GetAudioEncoder()->GetBitRate()*1000);

        List<BYTE> esDecoderDescriptor;
        BufferOutputSerializer esDecoderOut(esDecoderDescriptor);
        esDecoderOut.OutputByte(bMP3 ? 107 : 64);
        esDecoderOut.OutputByte(0x15); //stream/type flags.  always 0x15 for my purposes.
        esDecoderOut.OutputByte(0); //buffer size, just set it to 1536 for both mp3 and aac
        esDecoderOut.OutputWord(WORD_BE(0x600)); 
        esDecoderOut.OutputDword(maxBitRate); //max bit rate (cue bill 'o reily meme for these two)
        esDecoderOut.OutputDword(maxBitRate); //avg bit rate

        if(!bMP3) //if AAC, put in headers
        {
            esDecoderOut.OutputByte(0x5);  //decoder specific descriptor type
            /*esDecoderOut.OutputByte(0x80); //some stuff that no one should probably care about
            esDecoderOut.OutputByte(0x80);
            esDecoderOut.OutputByte(0x80);*/
            esDecoderOut.OutputByte(AACHeader.Num());
            esDecoderOut.Serialize((LPVOID)AACHeader.Array(), AACHeader.Num());
        }


        List<BYTE> esDescriptor;
        BufferOutputSerializer esOut(esDescriptor);
        esOut.OutputWord(0); //es id
        esOut.OutputByte(0); //stream priority
        esOut.OutputByte(4); //descriptor type
        /*esOut.OutputByte(0x80); //some stuff that no one should probably care about
        esOut.OutputByte(0x80);
        esOut.OutputByte(0x80);*/
        esOut.OutputByte(esDecoderDescriptor.Num());
        esOut.Serialize((LPVOID)esDecoderDescriptor.Array(), esDecoderDescriptor.Num());
        esOut.OutputByte(0x6);  //config descriptor type
        /*esOut.OutputByte(0x80); //some stuff that no one should probably care about
        esOut.OutputByte(0x80);
        esOut.OutputByte(0x80);*/
        esOut.OutputByte(1); //len
        esOut.OutputByte(2); //SL value(? always 2)

        //-------------------------------------------

        PushBox(output, DWORD_BE('moov'));

          //------------------------------------------------------
          // header
          PushBox(output, DWORD_BE('mvhd'));
            output.OutputDword(0); //version and flags (none)
            output.OutputDword(macTime); //creation time
            output.OutputDword(macTime); //modified time
            output.OutputDword(DWORD_BE(1000)); //time base (milliseconds, so 1000)
            output.OutputDword(videoDuration); //duration (in time base units)
            output.OutputDword(DWORD_BE(0x00010000)); //fixed point playback speed 1.0
            output.OutputWord(WORD_BE(0x0100)); //fixed point vol 1.0
            output.OutputQword(0); //reserved (10 bytes)
            output.OutputWord(0);
            output.OutputDword(DWORD_BE(0x00010000)); output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00000000)); //window matrix row 1 (1.0, 0.0, 0.0)
            output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00010000)); output.OutputDword(DWORD_BE(0x00000000)); //window matrix row 2 (0.0, 1.0, 0.0)
            output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x40000000)); //window matrix row 3 (0.0, 0.0, 16384.0)
            output.OutputDword(0); //prevew start time (time base units)
            output.OutputDword(0); //prevew duration (time base units)
            output.OutputDword(0); //still poster frame (timestamp of frame)
            output.OutputDword(0); //selection(?) start time (time base units)
            output.OutputDword(0); //selection(?) duration (time base units)
            output.OutputDword(0); //current time (0, time base units)
            output.OutputDword(DWORD_BE(3)); //next free track id (1-based rather than 0-based)
          PopBox(output); //mvhd

          //------------------------------------------------------
          // audio track
          PushBox(output, DWORD_BE('trak'));
            PushBox(output, DWORD_BE('tkhd')); //track header
              output.OutputDword(DWORD_BE(0x00000007)); //version (0) and flags (0xF)
              output.OutputDword(macTime); //creation time
              output.OutputDword(macTime); //modified time
              output.OutputDword(DWORD_BE(1)); //track ID
              output.OutputDword(0); //reserved
              output.OutputDword(audioDuration); //duration (in time base units)
              output.OutputQword(0); //reserved
              output.OutputWord(0); //video layer (0)
              output.OutputWord(WORD_BE(0)); //quicktime alternate track id
              output.OutputWord(WORD_BE(0x0100)); //volume
              output.OutputWord(0); //reserved
              output.OutputDword(DWORD_BE(0x00010000)); output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00000000)); //window matrix row 1 (1.0, 0.0, 0.0)
              output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00010000)); output.OutputDword(DWORD_BE(0x00000000)); //window matrix row 2 (0.0, 1.0, 0.0)
              output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x40000000)); //window matrix row 3 (0.0, 0.0, 16384.0)
              output.OutputDword(0); //width (fixed point)
              output.OutputDword(0); //height (fixed point)
            PopBox(output); //tkhd
            /*PushBox(output, DWORD_BE('edts'));
              PushBox(output, DWORD_BE('elst'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(DWORD_BE(1)); //count
                output.OutputDword(audioDuration); //duration
                output.OutputDword(0); //start time
                output.OutputDword(DWORD_BE(0x00010000)); //playback speed (1.0)
              PopBox(); //elst
            PopBox(); //tdst*/
            PushBox(output, DWORD_BE('mdia'));
              PushBox(output, DWORD_BE('mdhd'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(macTime); //creation time
                output.OutputDword(macTime); //modified time
                output.OutputDword(DWORD_BE(App->GetSampleRateHz())); //time scale
                output.OutputDword(audioUnitDuration);
                output.OutputDword(bMP3 ? DWORD_BE(0x55c40000) : DWORD_BE(0x15c70000));
              PopBox(output); //mdhd
              PushBox(output, DWORD_BE('hdlr'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(0); //quicktime type (none)
                output.OutputDword(DWORD_BE('soun')); //media type
                output.OutputDword(0); //manufacturer reserved
                output.OutputDword(0); //quicktime component reserved flags
                output.OutputDword(0); //quicktime component reserved mask
                output.Serialize((LPVOID)lpAudioTrack, (DWORD)strlen(lpAudioTrack)+1); //track name
              PopBox(output); //hdlr
              PushBox(output, DWORD_BE('minf'));
                PushBox(output, DWORD_BE('smhd'));
                  output.OutputDword(0); //version and flags (none)
                  output.OutputDword(0); //balance (fixed point)
                PopBox(output); //vdhd
                PushBox(output, DWORD_BE('dinf'));
                  PushBox(output, DWORD_BE('dref'));
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(DWORD_BE(1)); //count
                    PushBox(output, DWORD_BE('url '));
                      output.OutputDword(DWORD_BE(0x00000001)); //version (0) and flags (1)
                    PopBox(output); //url
                  PopBox(output); //dref
                PopBox(output); //dinf
                PushBox(output, DWORD_BE('stbl'));
                  PushBox(output, DWORD_BE('stsd'));
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(DWORD_BE(1)); //count
                    PushBox(output, DWORD_BE('mp4a'));
                      output.OutputDword(0); //reserved (6 bytes)
                      output.OutputWord(0);
                      output.OutputWord(WORD_BE(1)); //dref index
                      output.OutputWord(0); //quicktime encoding version
                      output.OutputWord(0); //quicktime encoding revision
                      output.OutputDword(0); //quicktime audio encoding vendor
                      output.OutputWord(0); //channels (ignored)
                      output.OutputWord(WORD_BE(16)); //sample size
                      output.OutputWord(0); //quicktime audio compression id
                      output.OutputWord(0); //quicktime audio packet size
                      output.OutputDword(DWORD_BE(App->GetSampleRateHz()<<16)); //sample rate (fixed point)
                      PushBox(output, DWORD_BE('esds'));
                        output.OutputDword(0); //version and flags (none)
                        output.OutputByte(3); //ES descriptor type
                        /*output.OutputByte(0x80);
                        output.OutputByte(0x80);
                        output.OutputByte(0x80);*/
                        output.OutputByte(esDescriptor.Num());
                        output.Serialize((LPVOID)esDescriptor.Array(), esDescriptor.Num());
                      PopBox(output);
                    PopBox(output);
                  PopBox(output); //stsd
                  PushBox(output, DWORD_BE('stts')); //list of keyframe (i-frame) IDs
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(fastHtonl(audioDecodeTimes.Num()));
                    for(UINT i=0; i<audioDecodeTimes.Num(); i++)
                    {
                        output.OutputDword(fastHtonl(audioDecodeTimes[i].count));
                        output.OutputDword(fastHtonl(audioDecodeTimes[i].val));
                    }
                  PopBox(output); //stss
                  PushBox(output, DWORD_BE('stsc')); //sample to chunk list
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(fastHtonl(audioSampleToChunk.Num()));
                    for(UINT i=0; i<audioSampleToChunk.Num(); i++)
                    {
                        SampleToChunk &stc  = audioSampleToChunk[i];
                        output.OutputDword(fastHtonl(stc.firstChunkID));
                        output.OutputDword(fastHtonl(stc.samplesPerChunk));
                        output.OutputDword(DWORD_BE(1));
                    }
                  PopBox(output); //stsc

                  //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 30, 0);
                  //ProcessEvents();

                  PushBox(output, DWORD_BE('stsz')); //sample sizes
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(0); //block size for all (0 if differing sizes)
                    output.OutputDword(fastHtonl(audioFrames.Num()));
                    for(UINT i=0; i<audioFrames.Num(); i++)
                        output.OutputDword(fastHtonl(audioFrames[i].size));
                  PopBox(output);

                  //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 40, 0);
                  //ProcessEvents();

                  if(audioChunks.Num() && audioChunks.Last() > 0xFFFFFFFFLL)
                  {
                      PushBox(output, DWORD_BE('co64')); //chunk offsets
                      output.OutputDword(0); //version and flags (none)
                      output.OutputDword(fastHtonl(audioChunks.Num()));
                      for(UINT i=0; i<audioChunks.Num(); i++)
                          output.OutputQword(fastHtonll(audioChunks[i]));
                      PopBox(output); //co64
                  }
                  else
                  {
                      PushBox(output, DWORD_BE('stco')); //chunk offsets
                        output.OutputDword(0); //version and flags (none)
                        output.OutputDword(fastHtonl(audioChunks.Num()));
                        for(UINT i=0; i<audioChunks.Num(); i++)
                            output.OutputDword(fastHtonl((DWORD)audioChunks[i]));
                      PopBox(output); //stco
                  }
                PopBox(output); //stbl
              PopBox(output); //minf
            PopBox(output); //mdia
          PopBox(output); //trak

          //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 50, 0);
          //ProcessEvents();

          //------------------------------------------------------
          // video track
          PushBox(output, DWORD_BE('trak'));
            PushBox(output, DWORD_BE('tkhd')); //track header
              output.OutputDword(DWORD_BE(0x00000007)); //version (0) and flags (0x7)
              output.OutputDword(macTime); //creation time
              output.OutputDword(macTime); //modified time
              output.OutputDword(DWORD_BE(2)); //track ID
              output.OutputDword(0); //reserved
              output.OutputDword(videoDuration); //duration (in time base units)
              output.OutputQword(0); //reserved
              output.OutputWord(0); //video layer (0)
              output.OutputWord(0); //quicktime alternate track id (0)
              output.OutputWord(0); //track audio volume (this is video, so 0)
              output.OutputWord(0); //reserved
              output.OutputDword(DWORD_BE(0x00010000)); output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00000000)); //window matrix row 1 (1.0, 0.0, 0.0)
              output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00010000)); output.OutputDword(DWORD_BE(0x00000000)); //window matrix row 2 (0.0, 1.0, 0.0)
              output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x00000000)); output.OutputDword(DWORD_BE(0x40000000)); //window matrix row 3 (0.0, 0.0, 16384.0)
              output.OutputDword(fastHtonl(width<<16));  //width (fixed point)
              output.OutputDword(fastHtonl(height<<16)); //height (fixed point)
            PopBox(output); //tkhd
            /*PushBox(output, DWORD_BE('edts'));
              PushBox(output, DWORD_BE('elst'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(DWORD_BE(1)); //count
                output.OutputDword(videoDuration); //duration
                output.OutputDword(0); //start time
                output.OutputDword(DWORD_BE(0x00010000)); //playback speed (1.0)
              PopBox(); //elst
            PopBox(); //tdst*/
            PushBox(output, DWORD_BE('mdia'));
              PushBox(output, DWORD_BE('mdhd'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(macTime); //creation time
                output.OutputDword(macTime); //modified time
                output.OutputDword(DWORD_BE(1000)); //time scale
                output.OutputDword(videoDuration);
                output.OutputDword(DWORD_BE(0x55c40000));
              PopBox(output); //mdhd
              PushBox(output, DWORD_BE('hdlr'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(0); //quicktime type (none)
                output.OutputDword(DWORD_BE('vide')); //media type
                output.OutputDword(0); //manufacturer reserved
                output.OutputDword(0); //quicktime component reserved flags
                output.OutputDword(0); //quicktime component reserved mask
                output.Serialize((LPVOID)lpVideoTrack, (DWORD)strlen(lpVideoTrack)+1); //track name
              PopBox(output); //hdlr
              PushBox(output, DWORD_BE('minf'));
                PushBox(output, DWORD_BE('vmhd'));
                  output.OutputDword(DWORD_BE(0x00000001)); //version (0) and flags (1)
                  output.OutputWord(0); //quickdraw graphic mode (copy = 0)
                  output.OutputWord(0); //quickdraw red value
                  output.OutputWord(0); //quickdraw green value
                  output.OutputWord(0); //quickdraw blue value
                PopBox(output); //vdhd
                PushBox(output, DWORD_BE('dinf'));
                  PushBox(output, DWORD_BE('dref'));
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(DWORD_BE(1)); //count
                    PushBox(output, DWORD_BE('url '));
                      output.OutputDword(DWORD_BE(0x00000001)); //version (0) and flags (1)
                    PopBox(output); //url
                  PopBox(output); //dref
                PopBox(output); //dinf
                PushBox(output, DWORD_BE('stbl'));
                  PushBox(output, DWORD_BE('stsd'));
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(DWORD_BE(1)); //count
                    PushBox(output, DWORD_BE('avc1'));
                      output.OutputDword(0); //reserved 6 bytes
                      output.OutputWord(0);
                      output.OutputWord(WORD_BE(1)); //index
                      output.OutputWord(0); //encoding version
                      output.OutputWord(0); //encoding revision level
                      output.OutputDword(0); //encoding vendor
                      output.OutputDword(0); //temporal quality
                      output.OutputDword(0); //spatial quality
                      output.OutputWord(fastHtons(width)); //width
                      output.OutputWord(fastHtons(height)); //height
                      output.OutputDword(DWORD_BE(0x00480000)); //fixed point width pixel resolution (72.0)
                      output.OutputDword(DWORD_BE(0x00480000)); //fixed point height pixel resolution (72.0)
                      output.OutputDword(0); //quicktime video data size 
                      output.OutputWord(WORD_BE(1)); //frame count(?)
                      output.OutputByte((BYTE)strlen(videoCompressionName)); //compression name length
                      output.Serialize(videoCompressionName, 31); //31 bytes for the name
                      output.OutputWord(WORD_BE(24)); //bit depth
                      output.OutputWord(0xFFFF); //quicktime video color table id (none = -1)
                      PushBox(output, DWORD_BE('avcC'));
                        output.OutputByte(1); //version
                        output.OutputByte(100); //h264 profile ID
                        output.OutputByte(0); //h264 compatible profiles
                        output.OutputByte(0x1f); //h264 level
                        output.OutputByte(0xff); //reserved
                        output.OutputByte(0xe1); //first half-byte = no clue. second half = sps count
                        output.OutputWord(fastHtons(SPS.Num())); //sps size
                        output.Serialize(SPS.Array(), SPS.Num()); //sps data
                        output.OutputByte(1); //pps count
                        output.OutputWord(fastHtons(PPS.Num())); //pps size
                        output.Serialize(PPS.Array(), PPS.Num()); //pps data
                      PopBox(output); //avcC
                    PopBox(output); //avc1
                  PopBox(output); //stsd
                  PushBox(output, DWORD_BE('stts')); //frame times
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(fastHtonl(videoDecodeTimes.Num()));
                    for(UINT i=0; i<videoDecodeTimes.Num(); i++)
                    {
                        output.OutputDword(fastHtonl(videoDecodeTimes[i].count));
                        output.OutputDword(fastHtonl(videoDecodeTimes[i].val));
                    }
                  PopBox(output); //stts

                  //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 60, 0);
                  //ProcessEvents();

                  if (IFrameIDs.Num())
                  {
                      PushBox(output, DWORD_BE('stss')); //list of keyframe (i-frame) IDs
                        output.OutputDword(0); //version and flags (none)
                        output.OutputDword(fastHtonl(IFrameIDs.Num()));
                        output.Serialize(IFrameIDs.Array(), IFrameIDs.Num()*sizeof(UINT));
                      PopBox(output); //stss
                  }
                  PushBox(output, DWORD_BE('ctts')); //list of composition time offsets
                    output.OutputDword(0); //version (0) and flags (none)
                    //output.OutputDword(DWORD_BE(0x01000000)); //version (1) and flags (none)

                    output.OutputDword(fastHtonl(compositionOffsets.Num()));
                    for(UINT i=0; i<compositionOffsets.Num(); i++)
                    {
                        output.OutputDword(fastHtonl(compositionOffsets[i].count));
                        output.OutputDword(fastHtonl(compositionOffsets[i].val));
                    }
                  PopBox(output); //ctts

                  //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 70, 0);
                  //ProcessEvents();

                  PushBox(output, DWORD_BE('stsc')); //sample to chunk list
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(fastHtonl(videoSampleToChunk.Num()));
                    for(UINT i=0; i<videoSampleToChunk.Num(); i++)
                    {
                        SampleToChunk &stc  = videoSampleToChunk[i];
                        output.OutputDword(fastHtonl(stc.firstChunkID));
                        output.OutputDword(fastHtonl(stc.samplesPerChunk));
                        output.OutputDword(DWORD_BE(1));
                    }
                  PopBox(output); //stsc
                  PushBox(output, DWORD_BE('stsz')); //sample sizes
                    output.OutputDword(0); //version and flags (none)
                    output.OutputDword(0); //block size for all (0 if differing sizes)
                    output.OutputDword(fastHtonl(videoFrames.Num()));
                    for(UINT i=0; i<videoFrames.Num(); i++)
                        output.OutputDword(fastHtonl(videoFrames[i].size));
                  PopBox(output);

                  if(videoChunks.Num() && videoChunks.Last() > 0xFFFFFFFFLL)
                  {
                      PushBox(output, DWORD_BE('co64')); //chunk offsets
                      output.OutputDword(0); //version and flags (none)
                      output.OutputDword(fastHtonl(videoChunks.Num()));
                      for(UINT i=0; i<videoChunks.Num(); i++)
                          output.OutputQword(fastHtonll(videoChunks[i]));
                      PopBox(output); //co64
                  }
                  else
                  {
                      PushBox(output, DWORD_BE('stco')); //chunk offsets
                        output.OutputDword(0); //version and flags (none)
                        output.OutputDword(fastHtonl(videoChunks.Num()));
                        for(UINT i=0; i<videoChunks.Num(); i++)
                            output.OutputDword(fastHtonl((DWORD)videoChunks[i]));
                      PopBox(output); //stco
                  }
                PopBox(output); //stbl
              PopBox(output); //minf
            PopBox(output); //mdia
          PopBox(output); //trak

          //SendMessage(GetDlgItem(hwndProgressDialog, IDC_PROGRESS1), PBM_SETPOS, 80, 0);
          //ProcessEvents();

          //------------------------------------------------------
          // info thingy
          PushBox(output, DWORD_BE('udta'));
            PushBox(output, DWORD_BE('meta'));
              output.OutputDword(0); //version and flags (none)
              PushBox(output, DWORD_BE('hdlr'));
                output.OutputDword(0); //version and flags (none)
                output.OutputDword(0); //quicktime type
                output.OutputDword(DWORD_BE('mdir')); //metadata type
                output.OutputDword(DWORD_BE('appl')); //quicktime manufacturer reserved thingy
                output.OutputDword(0); //quicktime component reserved flag
                output.OutputDword(0); //quicktime component reserved flag mask
                output.OutputByte(0); //null string
              PopBox(output); //hdlr
              PushBox(output, DWORD_BE('ilst'));
                PushBox(output, DWORD_BE('\xa9too'));
                  PushBox(output, DWORD_BE('data'));
                    output.OutputDword(DWORD_BE(1)); //version (1) + flags (0)
                    output.OutputDword(0); //reserved
                    LPSTR lpVersion = OBS_VERSION_STRING_ANSI;
                    output.Serialize(lpVersion, (DWORD)strlen(lpVersion));
                  PopBox(output); //data
                PopBox(output); //@too
              PopBox(output); //ilst
            PopBox(output); //meta
          PopBox(output); //udta

        PopBox(output); //moov

        fileOut.Serialize(endBuffer.Array(), (DWORD)output.GetPos());
        fileOut.Close();

        XFile file;
        if(file.Open(strFile, XFILE_WRITE, XFILE_OPENEXISTING))
        {
#ifdef USE_64BIT_MP4
            file.SetPos((INT64)mdatStart+8, XFILE_BEGIN);

            UINT64 size = fastHtonll(mdatStop-mdatStart);
            file.Write(&size, 8);
#else
            file.SetPos((INT64)mdatStart, XFILE_BEGIN);
            UINT size = fastHtonl((DWORD)(mdatStop-mdatStart));
            file.Write(&size, 4);
#endif
            file.Close();
        }

        App->EnableSceneSwitching(true);

        //DestroyWindow(hwndProgressDialog);
    }
示例#3
0
    bool Init(CTSTR lpFile)
    {
        strFile = lpFile;

        initialTimeStamp = -1;

        if(!fileOut.Open(lpFile, XFILE_CREATEALWAYS, 1024*1024))
            return false;

        fileOut.OutputDword(DWORD_BE(0x20));
        fileOut.OutputDword(DWORD_BE('ftyp'));
        fileOut.OutputDword(DWORD_BE('isom'));
        fileOut.OutputDword(DWORD_BE(0x200));
        fileOut.OutputDword(DWORD_BE('isom'));
        fileOut.OutputDword(DWORD_BE('iso2'));
        fileOut.OutputDword(DWORD_BE('avc1'));
        fileOut.OutputDword(DWORD_BE('mp41'));

        fileOut.OutputDword(DWORD_BE(0x8));
        fileOut.OutputDword(DWORD_BE('free'));

        mdatStart = fileOut.GetPos();
        fileOut.OutputDword(DWORD_BE(0x1));
        fileOut.OutputDword(DWORD_BE('mdat'));
#ifdef USE_64BIT_MP4
        fileOut.OutputQword(0);
#endif

        bMP3 = scmp(App->GetAudioEncoder()->GetCodec(), TEXT("MP3")) == 0;

        audioFrameSize = App->GetAudioEncoder()->GetFrameSize();

        bStreamOpened = true;

        return true;
    }
示例#4
0
文件: img4.c 项目: big538/img4tool
int
main(int argc, char **argv)
{
    int rv;
    const char *what;
    const char *filename;
    const char *outname;

    TheImg4 *img4;
    unsigned type;
    unsigned written;
    unsigned char ivkey[16 + 32];
    unsigned char *iv = NULL, *key = NULL;
    unsigned char *output = NULL;
    unsigned outlen = 0;
    int outdup = 0;

    DERItem item;
    unsigned char *data;
    size_t size;

    if (argc < 4) {
        fprintf(stderr, "usage: %s {-image|-extra|-keybag|-ticket} input output [ivkey]\n", argv[0]);
        return 1;
    }

    what = argv[1];
    filename = argv[2];
    outname = argv[3];
    if (argc > 4) {
        rv = str2hex(sizeof(ivkey), ivkey, argv[4]);
        if (rv == sizeof(ivkey)) {
            iv = ivkey;
            key = ivkey + 16;
        }
    }

    data = read_file(filename, 0, &size);
    if (data == NULL) {
        fprintf(stderr, "[e] cannot read '%s'\n", filename);
        return -1;
    }

    img4 = parse(data, size);
    if (!img4) {
        fprintf(stderr, "[e] cannot parse '%s'\n", filename);
        free(data);
        return -1;
    }

    rv = Img4DecodeGetPayloadType(img4, &type);
    if (rv) {
        fprintf(stderr, "[e] cannot identify '%s'\n", filename);
        goto err;
    }
    printf("%c%c%c%c\n", FOURCC(type));

    if (!strncmp(what, "-i", 2) || !strncmp(what, "-e", 2)) {
        int decompress;

        rv = Img4DecodeGetPayload(img4, &item);
        if (rv) {
            fprintf(stderr, "[e] cannot extract payload from '%s'\n", filename);
            goto err;
        }
        output = item.data;
        outlen = item.length;

        if (iv && key) {
            if (outlen & 15) {
                unsigned usize = (outlen + 15) & ~15;
                unsigned char *tmp = calloc(1, usize);
                if (!tmp) {
                    fprintf(stderr, "[e] out of memory %u\n", usize);
                    goto err;
                }
                memcpy(tmp, output, outlen);
                OUTSET(tmp);
            }

            rv = Img4DecodeGetPayloadKeybag(img4, &item);
            if (rv || item.length == 0) {
                fprintf(stderr, "[w] image '%s' has no keybag\n", filename);
            }
#ifdef USE_CORECRYPTO
            cccbc_one_shot(ccaes_cbc_decrypt_mode(), 32, key, iv, (outlen + 15) / 16, output, output);
#else
            AES_KEY decryptKey;
            AES_set_decrypt_key(key, 256, &decryptKey);
            AES_cbc_encrypt(output, output, (outlen + 15) & ~15, &decryptKey, iv, AES_DECRYPT);
#endif
        }

#ifdef iOS10
        if (img4->payload.compression.data && img4->payload.compression.length) {
            DERItem tmp[2];
            uint32_t deco = 0;
            uint64_t usize = 0;
            if (DERParseSequenceContent(&img4->payload.compression, 2, DERImg4PayloadItemSpecs10c, tmp, 0) ||
                DERParseInteger(&tmp[0], &deco) || DERParseInteger64(&tmp[1], &usize)) {
                fprintf(stderr, "[e] cannot get decompression info\n");
                goto err;
            }
            if (deco == 1 && what[1] == 'i') {
                size_t asize = lzfse_decode_scratch_size();
                unsigned char *dec, *aux = malloc(asize);
                if (!aux) {
                    fprintf(stderr, "[e] out of memory %zu\n", asize);
                    goto err;
                }
                dec = malloc(usize + 1);
                if (!dec) {
                    fprintf(stderr, "[e] out of memory %llu\n", usize + 1);
                    free(aux);
                    goto err;
                }
                outlen = lzfse_decode_buffer(dec, usize + 1, output, outlen, aux);
                free(aux);
                if (outlen != usize) {
                    fprintf(stderr, "[e] decompression error\n");
                    free(dec);
                    goto err;
                }
                OUTSET(dec);
            }
        }
#endif
        decompress = (DWORD_BE(output, 0) == 'comp' && DWORD_BE(output, 4) == 'lzss');
        if (decompress && what[1] == 'i') {
            uint32_t csize = DWORD_BE(output, 16);
            uint32_t usize = DWORD_BE(output, 12);
            uint32_t adler = DWORD_BE(output, 8);
            unsigned char *dec = malloc(usize);
            if (outlen > 0x180 + csize) {
                fprintf(stderr, "[i] extra 0x%x bytes after compressed chunk\n", outlen - 0x180 - csize);
            }
            if (!dec) {
                fprintf(stderr, "[e] out of memory %u\n", usize);
                goto err;
            }
            outlen = decompress_lzss(dec, output + 0x180, csize);
            if (adler != lzadler32(dec, outlen)) {
                fprintf(stderr, "[w] adler32 mismatch\n");
            }
            OUTSET(dec);
        } else if (decompress) {
            uint32_t csize = DWORD_BE(output, 16);
            uint32_t usize = outlen - 0x180 - csize;
            if (outlen > 0x180 + csize) {
                unsigned char *dec = malloc(usize);
                if (!dec) {
                    fprintf(stderr, "[e] out of memory %u\n", usize);
                    goto err;
                }
                memcpy(dec, output + 0x180 + csize, usize);
                outlen = usize;
                OUTSET(dec);
            } else {
                OUTSET(NULL);
            }
        } else if (what[1] == 'e') {
            OUTSET(NULL);
        }
        if (!output) {
            fprintf(stderr, "[e] nothing to do\n");
            goto err;
        }
    }
    if (!strncmp(what, "-k", 2)) {
        rv = Img4DecodeGetPayloadKeybag(img4, &item);
        if (rv == 0 && item.length) {
            output = item.data;
            outlen = item.length;
        } else {
            fprintf(stderr, "[e] image '%s' has no keybag\n", filename);
            goto err;
        }
    }
    if (!strncmp(what, "-t", 2)) {
        bool exists = false;
        rv = Img4DecodeManifestExists(img4, &exists);
        if (rv == 0 && exists) {
            output = img4->manifestRaw.data;
            outlen = img4->manifestRaw.length;
        } else {
            fprintf(stderr, "[e] image '%s' has no ticket\n", filename);
            goto err;
        }
    }

    written = write_file(outname, output, outlen);
    if (written != outlen) {
        fprintf(stderr, "[e] cannot write '%s'\n", outname);
        goto err;
    }

    rv = 0;
out:
    if (outdup) {
        free(output);
    }
    free(img4);
    free(data);
    return rv;

err:
    rv = -1;
    goto out;
}
示例#5
0
/*
=======================================
    PNG 文件读取
=======================================
*/
CR_API sFMT_PIC*
load_cr_png (
  __CR_IO__ iDATIN*         datin,
  __CR_IN__ const sLOADER*  param
    )
{
    leng_t  nbpl;
    leng_t  sbpp;
    leng_t  dptr;
    uint_t  fcrh;
    uint_t  index;
    uchar*  image;
    uchar*  sdata;
    uchar*  ddata;
    leng_t  dsize;
    int32u  ssize;
    uint_t  ww, hh;
    byte_t  pal[768];
    /* ----------- */
    fsize_t     fsze;
    sPNG_HDR    head;
    sFMT_PIC*   rett;
    sFMT_FRAME  temp;

    /* 这个参数可能为空 */
    if (datin == NULL)
        return (NULL);

    /* 读取 & 检查头部 */
    if (!(CR_VCALL(datin)->geType(datin, &head, sPNG_HDR)))
        return (NULL);
    if (mem_cmp(&head, "\x89PNG\r\n\x1A\n\0\0\0\x0DIHDR", 16) != 0)
        return (NULL);
    if (head.info.compr != 0 || head.info.filter != 0 ||
        head.info.interlace != 0)
        return (NULL);

    /* 对宽高的截断检查 */
    if (cut_int32_u(&ww, DWORD_BE(head.info.w)))
        return (NULL);
    if (cut_int32_u(&hh, DWORD_BE(head.info.h)))
        return (NULL);

    /* 生成图片对象 */
    mem_zero(temp.wh, sizeof(temp.wh));
    switch (head.info.color)
    {
        case 0: /* 灰度图像 */
            if (head.info.depth != 1 &&
                head.info.depth != 2 &&
                head.info.depth != 4 &&
                head.info.depth != 8 &&
                head.info.depth != 16)
                return (NULL);
            fcrh = CR_INDEX8;
            temp.fmt = CR_PIC_GREY;
            temp.bpp = head.info.depth;
            temp.clr = "I";
            temp.wh[0] = head.info.depth;
            break;

        case 2: /* 真彩图像 */
            if (head.info.depth != 8 &&
                head.info.depth != 16)
                return (NULL);
            fcrh = CR_ARGB888;
            temp.fmt = CR_PIC_ARGB;
            temp.bpp = head.info.depth * 3;
            temp.clr = "BGR";
            temp.wh[0] = head.info.depth;
            temp.wh[1] = head.info.depth;
            temp.wh[2] = head.info.depth;
            break;

        case 3: /* 索引图像 */
            if (head.info.depth != 1 &&
                head.info.depth != 2 &&
                head.info.depth != 4 &&
                head.info.depth != 8)
                return (NULL);
            fcrh = CR_INDEX8;
            temp.fmt = CR_PIC_PALS;
            temp.bpp = head.info.depth;
            temp.clr = "P";
            temp.wh[0] = head.info.depth;
            break;

        case 4: /* α灰度图像 */
            if (head.info.depth != 8 &&
                head.info.depth != 16)
                return (NULL);
            fcrh = CR_ARGB8888;
            temp.fmt = CR_PIC_GREY;
            temp.bpp = head.info.depth * 2;
            temp.clr = "AI";
            temp.wh[0] = head.info.depth;
            temp.wh[1] = head.info.depth;
            break;

        case 6: /* α真彩图像 */
            if (head.info.depth != 8 &&
                head.info.depth != 16)
                return (NULL);
            fcrh = CR_ARGB8888;
            temp.fmt = CR_PIC_ARGB;
            temp.bpp = head.info.depth * 4;
            temp.clr = "ABGR";
            temp.wh[0] = head.info.depth;
            temp.wh[1] = head.info.depth;
            temp.wh[2] = head.info.depth;
            temp.wh[3] = head.info.depth;
            break;

        default:
            return (NULL);
    }
    sbpp = (temp.bpp - 1) / 8 + 1;
    temp.pic = image_new(0, 0, ww, hh, fcrh, FALSE, 4);
    if (temp.pic == NULL)
        return (NULL);

    /* 生成灰度调色板 */
    if (temp.fmt == CR_PIC_GREY)
        pal_set_gray8(temp.pic->pal, 256);

    /* 分配 IDAT 的内存 */
    fsze = dati_get_size(datin);
    if (fsze <= sizeof(sPNG_HDR) + sizeof(sIEND) * 2)
        goto _failure1;
    fsze -= sizeof(sPNG_HDR) + sizeof(sIEND) * 2;
    ddata = (byte_t*)mem_malloc64(fsze);
    if (ddata == NULL)
        goto _failure1;
    dsize = (leng_t)fsze;

    /* 读取数据块 */
    dptr = 0;
    fcrh = 256;         /* 这个保存调色板颜色数 */
    do
    {
        /* 数据块大小 */
        if (!(CR_VCALL(datin)->geType(datin, &head.info, sCHUNK)))
            goto _failure2;
        ssize = DWORD_BE(head.info.head.size);
        if (ssize > fsze)
            goto _failure2;

        if (head.info.head.name == mk_tag4("PLTE"))
        {
            /* 调色板, 安全检查 */
            if (ssize > 768 || ssize % 3 != 0)
                goto _failure2;
            if (CR_VCALL(datin)->read(datin, pal, ssize) != ssize)
                goto _failure2;

            /* 转换到 4B 格式 */
            fcrh = (uint_t)ssize / 3;
            pal_3b_to_4b_sw(temp.pic->pal, pal, fcrh);
        }
        else
        if (head.info.head.name == mk_tag4("IDAT"))
        {
            /* 检查缓冲溢出 */
            if (dsize < ssize)
                goto _failure2;
            if (CR_VCALL(datin)->read(datin, ddata + dptr, ssize) != ssize)
                goto _failure2;
            dptr  += ssize;
            dsize -= ssize;
        }
        else
        if (head.info.head.name == mk_tag4("tRNS"))
        {
            /* 透明数据 */
            if (head.info.color == 0) {
                if (ssize != 2)
                    goto _failure2;
                if (CR_VCALL(datin)->read(datin, pal, 2) != 2)
                    goto _failure2;

                /* 调色板的这个颜色为透明色 */
                if (head.info.depth != 16)
                    temp.pic->pal[pal[1]] &= CDWORD_LE(0x00FFFFFFUL);
            }
            else
            if (head.info.color == 2) {
                if (ssize != 6)
                    goto _failure2;
                if (CR_VCALL(datin)->read(datin, pal, 6) != 6)
                    goto _failure2;

                /* 这个颜色为透明色, 这里只能展开来写
                   否则 C++Builder 2010 编译器编译时会崩溃 */
                if (head.info.depth != 16) {
                    temp.pic->keycolor  = pal[1];
                    temp.pic->keycolor <<= 8;
                    temp.pic->keycolor |= pal[3];
                    temp.pic->keycolor <<= 8;
                    temp.pic->keycolor |= pal[5];
                    temp.pic->keycolor |= 0xFF000000UL;
                    temp.pic->keycolor = DWORD_LE(temp.pic->keycolor);
                }
            }
            else
            if (head.info.color == 3) {
                if (ssize > fcrh)
                    goto _failure2;
                if (CR_VCALL(datin)->read(datin, pal, ssize) != ssize)
                    goto _failure2;

                /* 设置调色板的 Alpha 通道 */
                for (fcrh = (uint_t)ssize, index = 0; index < fcrh; index++)
                    ((uchar*)temp.pic->pal)[index * 4 + 3] = pal[index];
            }
            else {
                goto _failure2;
            }
        }
        else
        {
            /* 跳过其他数据块 */
            if (!CR_VCALL(datin)->seek(datin, ssize, SEEK_CUR))
                goto _failure2;
        }

        /* 跳过 CRC-32 */
        if (!CR_VCALL(datin)->seek(datin, 4, SEEK_CUR))
            goto _failure2;
    } while (head.info.head.name != mk_tag4("IEND"));

    /* 无 IDAT 块 */
    if (dptr == 0)
        goto _failure2;

    /* 分配带 filter 的图形内存 */
    if (cut_mad(&dsize, ww, sbpp * hh, hh))
        goto _failure2;
    sdata = (byte_t*)mem_malloc(dsize);
    if (sdata == NULL)
        goto _failure2;

    /* 解压图形数据 */
    dptr = uncompr_zlib(sdata, dsize, ddata, dptr);
    mem_free(ddata);
    ddata = sdata;
    if (dptr <= hh)
        goto _failure2;
    image = temp.pic->data;

    /* 文件解码完毕, 解析图片的像素数据 */
    if (temp.pic->fmt == CR_INDEX8)
    {
        switch (head.info.depth)
        {
            case 1:
                if (ww % 8 == 0)
                    nbpl = ww / 8;
                else
                    nbpl = ww / 8 + 1;
                if (!png_filter(ddata, nbpl, 1, hh, dptr))
                    goto _failure2;
                for (index = hh; index != 0; index--) {
                    sdata = (uchar*)font1_h2l(image, sdata, ww);
                    image += temp.pic->bpl;
                }
                break;

            case 2:
                if (ww % 4 == 0)
                    nbpl = ww / 4;
                else
                    nbpl = ww / 4 + 1;
                if (!png_filter(ddata, nbpl, 1, hh, dptr))
                    goto _failure2;
                for (index = hh; index != 0; index--) {
                    sdata = (uchar*)font2_h2l(image, sdata, ww);
                    image += temp.pic->bpl;
                }
                break;

            case 4:
                if (ww % 2 == 0)
                    nbpl = ww / 2;
                else
                    nbpl = ww / 2 + 1;
                if (!png_filter(ddata, nbpl, 1, hh, dptr))
                    goto _failure2;
                for (index = hh; index != 0; index--) {
                    sdata = (uchar*)font4_h2l(image, sdata, ww);
                    image += temp.pic->bpl;
                }
                break;

            case 8:
                nbpl = ww;
                if (!png_filter(ddata, nbpl, 1, hh, dptr))
                    goto _failure2;
                for (index = hh; index != 0; index--) {
                    mem_cpy(image, sdata, nbpl);
                    sdata += nbpl;
                    image += temp.pic->bpl;
                }
                break;

            default:
            case 16:
                nbpl = ww;
                nbpl *= 2;
                if (!png_filter(ddata, nbpl, 2, hh, dptr))
                    goto _failure2;
                for (index = hh; index != 0; index--) {
                    for (fcrh = 0; fcrh < ww; fcrh++, sdata += 2)
                        image[fcrh] = sdata[0];
                    image += temp.pic->bpl;
                }
                break;
        }
    }
    else
    {
        nbpl = ww * sbpp;
        if (!png_filter(ddata, nbpl, sbpp, hh, dptr))
            goto _failure2;
        nbpl = ww * temp.pic->bpc;

        switch (head.info.color)
        {
            case 2:
                if (head.info.depth == 8)
                {
                    /* 直接逐行复制 */
                    for (index = hh; index != 0; index--) {
                        for (dsize = 0; dsize < nbpl; dsize += 3) {
                            image[dsize + 0] = sdata[2];
                            image[dsize + 1] = sdata[1];
                            image[dsize + 2] = sdata[0];
                            sdata += 3;
                        }
                        image += temp.pic->bpl;
                    }
                }
                else
                {
                    /* 跳开一个像素复制 */
                    for (index = hh; index != 0; index--) {
                        for (dsize = 0; dsize < nbpl; dsize += 3) {
                            image[dsize + 0] = sdata[4];
                            image[dsize + 1] = sdata[2];
                            image[dsize + 2] = sdata[0];
                            sdata += 6;
                        }
                        image += temp.pic->bpl;
                    }
                }
                break;

            case 4:
                if (head.info.depth == 8)
                {
                    /* 直接逐行复制 */
                    for (index = hh; index != 0; index--) {
                        for (dsize = 0; dsize < nbpl; dsize += 4) {
                            image[dsize + 0] = sdata[0];
                            image[dsize + 1] = sdata[0];
                            image[dsize + 2] = sdata[0];
                            image[dsize + 3] = sdata[1];
                            sdata += 2;
                        }
                        image += temp.pic->bpl;
                    }
                }
                else
                {
                    /* 跳开一个像素复制 */
                    for (index = hh; index != 0; index--) {
                        for (dsize = 0; dsize < nbpl; dsize += 4) {
                            image[dsize + 0] = sdata[0];
                            image[dsize + 1] = sdata[0];
                            image[dsize + 2] = sdata[0];
                            image[dsize + 3] = sdata[2];
                            sdata += 4;
                        }
                        image += temp.pic->bpl;
                    }
                }
                break;

            default:
            case 6:
                if (head.info.depth == 8)
                {
                    /* 直接逐行复制 */
                    for (index = hh; index != 0; index--) {
                        for (dsize = 0; dsize < nbpl; dsize += 4) {
                            image[dsize + 0] = sdata[2];
                            image[dsize + 1] = sdata[1];
                            image[dsize + 2] = sdata[0];
                            image[dsize + 3] = sdata[3];
                            sdata += 4;
                        }
                        image += temp.pic->bpl;
                    }
                }
                else
                {
                    /* 跳开一个像素复制 */
                    for (index = hh; index != 0; index--) {
                        for (dsize = 0; dsize < nbpl; dsize += 4) {
                            image[dsize + 0] = sdata[4];
                            image[dsize + 1] = sdata[2];
                            image[dsize + 2] = sdata[0];
                            image[dsize + 3] = sdata[6];
                            sdata += 8;
                        }
                        image += temp.pic->bpl;
                    }
                }
                break;
        }
    }
    mem_free(ddata);

    /* 返回读取的文件数据 */
    rett = struct_new(sFMT_PIC);
    if (rett == NULL)
        goto _failure1;
    rett->frame = struct_dup(&temp, sFMT_FRAME);
    if (rett->frame == NULL) {
        mem_free(rett);
        goto _failure1;
    }
    CR_NOUSE(param);
    rett->type = CR_FMTZ_PIC;
    rett->count = 1;
    rett->infor = "Portable Network Graphics (PNG)";
    return (rett);

_failure2:
    mem_free(ddata);
_failure1:
    image_del(temp.pic);
    return (NULL);
}