コード例 #1
0
status_t CopyBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
        int64_t pts)
{
    //ALOGV("CopyBufferProvider(%p)::getNextBuffer(%p (%zu), %lld)",
    //        this, pBuffer, pBuffer->frameCount, pts);
    if (mLocalBufferFrameCount == 0) {
        status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
        if (res == OK) {
            copyFrames(pBuffer->raw, pBuffer->raw, pBuffer->frameCount);
        }
        return res;
    }
    if (mBuffer.frameCount == 0) {
        mBuffer.frameCount = pBuffer->frameCount;
        status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer, pts);
        // At one time an upstream buffer provider had
        // res == OK and mBuffer.frameCount == 0, doesn't seem to happen now 7/18/2014.
        //
        // By API spec, if res != OK, then mBuffer.frameCount == 0.
        // but there may be improper implementations.
        ALOG_ASSERT(res == OK || mBuffer.frameCount == 0);
        if (res != OK || mBuffer.frameCount == 0) { // not needed by API spec, but to be safe.
            pBuffer->raw = NULL;
            pBuffer->frameCount = 0;
            return res;
        }
        mConsumed = 0;
    }
    ALOG_ASSERT(mConsumed < mBuffer.frameCount);
    size_t count = min(mLocalBufferFrameCount, mBuffer.frameCount - mConsumed);
    count = min(count, pBuffer->frameCount);
    pBuffer->raw = mLocalBufferData;
    pBuffer->frameCount = count;
    copyFrames(pBuffer->raw, (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize,
            pBuffer->frameCount);
    return OK;
}
コード例 #2
0
SINT SoundSourceMediaFoundation::readSampleFrames(
        SINT numberOfFrames, CSAMPLE* sampleBuffer) {
    if (sDebug) {
        qDebug() << "read()" << numberOfFrames;
    }
    SINT framesNeeded(numberOfFrames);

    // first, copy frames from leftover buffer IF the leftover buffer is at
    // the correct frame
    if (m_leftoverBufferLength > 0 && m_leftoverBufferPosition == m_nextFrame) {
        copyFrames(sampleBuffer, &framesNeeded, m_leftoverBuffer,
                m_leftoverBufferLength);
        if (m_leftoverBufferLength > 0) {
            if (framesNeeded != 0) {
                qWarning() << __FILE__ << __LINE__
                        << "WARNING: Expected frames needed to be 0. Abandoning this file.";
                m_dead = true;
            }
            m_leftoverBufferPosition += numberOfFrames;
        }
    } else {
        // leftoverBuffer already empty or in the wrong position, clear it
        m_leftoverBufferLength = 0;
    }

    while (!m_dead && framesNeeded > 0) {
        HRESULT hr(S_OK);
        DWORD dwFlags(0);
        qint64 timestamp(0);
        IMFSample *pSample(nullptr);
        bool error(false); // set to true to break after releasing

        hr = m_pReader->ReadSample(MF_SOURCE_READER_FIRST_AUDIO_STREAM, // [in] DWORD dwStreamIndex,
                0,                                 // [in] DWORD dwControlFlags,
                nullptr,                      // [out] DWORD *pdwActualStreamIndex,
                &dwFlags,                        // [out] DWORD *pdwStreamFlags,
                &timestamp,                     // [out] LONGLONG *pllTimestamp,
                &pSample);                         // [out] IMFSample **ppSample
        if (FAILED(hr)) {
            qWarning() << "ReadSample failed!";
            break; // abort
        }

        if (sDebug) {
            qDebug() << "ReadSample timestamp:" << timestamp << "frame:"
                    << frameFromMF(timestamp, getSamplingRate()) << "dwflags:" << dwFlags;
        }

        if (dwFlags & MF_SOURCE_READERF_ERROR) {
            // our source reader is now dead, according to the docs
            qWarning()
                    << "SSMF: ReadSample set ERROR, SourceReader is now dead";
            m_dead = true;
            break;
        } else if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM) {
            qDebug() << "SSMF: End of input file.";
            break;
        } else if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) {
            qWarning() << "SSMF: Type change";
            break;
        } else if (pSample == nullptr) {
            // generally this will happen when dwFlags contains ENDOFSTREAM,
            // so it'll be caught before now -bkgood
            qWarning() << "SSMF: No sample";
            continue;
        } // we now own a ref to the instance at pSample

        IMFMediaBuffer *pMBuffer(nullptr);
        // I know this does at least a memcopy and maybe a malloc, if we have
        // xrun issues with this we might want to look into using
        // IMFSample::GetBufferByIndex (although MS doesn't recommend this)
        if (FAILED(hr = pSample->ConvertToContiguousBuffer(&pMBuffer))) {
            error = true;
            goto releaseSample;
        }
        CSAMPLE *buffer(nullptr);
        DWORD bufferLengthInBytes(0);
        hr = pMBuffer->Lock(reinterpret_cast<quint8**>(&buffer), nullptr, &bufferLengthInBytes);
        if (FAILED(hr)) {
            error = true;
            goto releaseMBuffer;
        }
        SINT bufferLength = samples2frames(bufferLengthInBytes / sizeof(buffer[0]));

        if (m_seeking) {
            qint64 bufferPosition(frameFromMF(timestamp, getSamplingRate()));
            if (sDebug) {
                qDebug() << "While seeking to " << m_nextFrame
                        << "WMF put us at" << bufferPosition;

            }
            if (m_nextFrame < bufferPosition) {
                // Uh oh. We are farther forward than our seek target. Emit
                // silence? We can't seek backwards here.
                CSAMPLE* pBufferCurpos = sampleBuffer
                        + frames2samples(numberOfFrames - framesNeeded);
                qint64 offshootFrames = bufferPosition - m_nextFrame;

                // If we can correct this immediately, write zeros and adjust
                // m_nextFrame to pretend it never happened.

                if (offshootFrames <= framesNeeded) {
                    qWarning() << __FILE__ << __LINE__
                            << "Working around inaccurate seeking. Writing silence for"
                            << offshootFrames << "frames";
                    // Set offshootFrames samples to zero.
                    memset(pBufferCurpos, 0,
                            sizeof(*pBufferCurpos) * frames2samples(offshootFrames));
                    // Now m_nextFrame == bufferPosition
                    m_nextFrame += offshootFrames;
                    framesNeeded -= offshootFrames;
                } else {
                    // It's more complicated. The buffer we have just decoded is
                    // more than framesNeeded frames away from us. It's too hard
                    // for us to handle this correctly currently, so let's just
                    // try to get on with our lives.
                    m_seeking = false;
                    m_nextFrame = bufferPosition;
                    qWarning() << __FILE__ << __LINE__
                            << "Seek offshoot is too drastic. Cutting losses and pretending the current decoded audio buffer is the right seek point.";
                }
            }

            if (m_nextFrame >= bufferPosition
                    && m_nextFrame < bufferPosition + bufferLength) {
                // m_nextFrame is in this buffer.
                buffer += frames2samples(m_nextFrame - bufferPosition);
                bufferLength -= m_nextFrame - bufferPosition;
                m_seeking = false;
            } else {
                // we need to keep going forward
                goto releaseRawBuffer;
            }
        }

        // If the bufferLength is larger than the leftover buffer, re-allocate
        // it with 2x the space.
        if (frames2samples(bufferLength) > m_leftoverBufferSize) {
            SINT newSize = m_leftoverBufferSize;

            while (newSize < frames2samples(bufferLength)) {
                newSize *= 2;
            }
            CSAMPLE* newBuffer = new CSAMPLE[newSize];
            memcpy(newBuffer, m_leftoverBuffer,
                    sizeof(m_leftoverBuffer[0]) * m_leftoverBufferSize);
            delete[] m_leftoverBuffer;
            m_leftoverBuffer = newBuffer;
            m_leftoverBufferSize = newSize;
        }
        copyFrames(
                sampleBuffer + frames2samples(numberOfFrames - framesNeeded),
                &framesNeeded,
                buffer, bufferLength);

        releaseRawBuffer: hr = pMBuffer->Unlock();
        // I'm ignoring this, MSDN for IMFMediaBuffer::Unlock stipulates
        // nothing about the state of the instance if this fails so might as
        // well just let it be released.
        //if (FAILED(hr)) break;
        releaseMBuffer: safeRelease(&pMBuffer);
        releaseSample: safeRelease(&pSample);
        if (error)
            break;
    }

    SINT framesRead = numberOfFrames - framesNeeded;
    m_iCurrentPosition += framesRead;
    m_nextFrame += framesRead;
    if (m_leftoverBufferLength > 0) {
        if (framesNeeded != 0) {
            qWarning() << __FILE__ << __LINE__
                    << "WARNING: Expected frames needed to be 0. Abandoning this file.";
            m_dead = true;
        }
        m_leftoverBufferPosition = m_nextFrame;
    }
    if (sDebug) {
        qDebug() << "read()" << numberOfFrames << "returning" << framesRead;
    }
    return framesRead;
}
コード例 #3
0
void ossimRpfToc::createTocAndCopyFrames( const ossimFilename& dotRpfFile,
                                          const ossimFilename& outputDir )
{
   static const char MODULE[] = "ossimRpfToc::createTocAndCopyFrames";

   if ( traceDebug() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << MODULE << " entered..."
         << "\ndot rpf file:      " << dotRpfFile
         << "\noutput directory:  " << outputDir
         << "\n";
   }

   if ( outputDir.expand().exists() == false )
   {
      if ( !outputDir.createDirectory(true, 0775) )
      {
         std::string e = MODULE;
         e += " ERROR:\nCould not create directory: ";
         e+= outputDir.c_str();
         throw ossimException(e);
      }
   }

   // Open the dot rpf file.
   std::ifstream* dotRpfStr = new std::ifstream;
   dotRpfStr->open(dotRpfFile, ios_base::in);
   if ( !dotRpfStr->good() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;

      std::string e = MODULE;
      e += " ERROR:\nCould not open: ";
      e += dotRpfFile.c_str();
      throw ossimException(e);
   }

   ossimFilename sourceADotTocFile = getSourceTocFile(*dotRpfStr);
   if ( sourceADotTocFile.empty() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;

      std::string e = MODULE;
      e += " ERROR:\nCould not deduce source a.toc file!";
      throw ossimException(e);
   }
   
   // Open the source a.toc file. Note the true flag is to keep the file header.
   ossimRefPtr<ossimRpfToc> sourceADotToc = new ossimRpfToc;
   if ( sourceADotToc->parseFile(sourceADotTocFile, true) != ossimErrorCodes::OSSIM_OK )
   {
      delete dotRpfStr;
      dotRpfStr = 0;
 
      std::string e = MODULE;
      e += " ERROR:\nCould not open: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e);
   }

   ossimRefPtr<const ossimNitfFileHeader> sourceNitfFileHdr = sourceADotToc->getNitfFileHeader();
   if ( !sourceNitfFileHdr.valid() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;        

      std::string e = MODULE;
      e += " ERROR:\nCould not get nitf file header from: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e);
   }
   
   ossimRefPtr<const ossimRpfHeader> sourceRpfHdr = sourceADotToc->getRpfHeader();
   if ( !sourceRpfHdr.valid() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;
      
      std::string e = MODULE;
      e += " ERROR:\nCould not get rpf header from: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e);
   }

   // Get the boundary rect sub header from the source a.toc.
   ossimRefPtr<ossimRpfBoundaryRectSectionSubheader> boundaryRectSectionSubheader =
      sourceRpfHdr->getNewBoundaryRectSectSubheader(sourceADotTocFile);
   if ( !boundaryRectSectionSubheader.valid() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;

      std::string e = MODULE;
      e += " ERROR:\nCould not pull boundary rect sub header from source file: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e);
   }   

   // Get the boundary rect table from the source a.toc.
   ossimRefPtr<ossimRpfBoundaryRectTable> boundaryRectTable =
      sourceRpfHdr->getNewBoundaryRectTable(sourceADotTocFile);
   if ( !boundaryRectTable.valid() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;
      
      std::string e = MODULE;
      e += " ERROR:\nCould not pull boundary rect table from source file: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e);
   }
   
   // Get the frame file subheader from the source a.toc.
   ossimRefPtr<ossimRpfFrameFileIndexSectionSubheader> frameFileSubHeader =
      sourceRpfHdr->getNewFrameFileIndexSectionSubheader(sourceADotTocFile);
   if ( !frameFileSubHeader.valid() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;

      std::string e = MODULE;
      e += " ERROR:\nCould not pull frame file sub header from source file: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e);
   }

   // Get the frame file subsection from the source a.toc.
   ossimRefPtr<ossimRpfFrameFileIndexSubsection> frameFileSubSection =
      sourceRpfHdr->getNewFileIndexSubsection(sourceADotTocFile);
   if ( !frameFileSubSection.valid() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;

      std::string e = MODULE;
      e += " ERROR:\nCould not pull frame file sub section from source file: ";
      e += sourceADotTocFile.c_str();
      throw ossimException(e); 
   }
   
   // Open the output file to write to.
   const ossimFilename A_DOT_TOC_FILE = "a.toc";
   ossimFilename dotTocFile = outputDir.dirCat(A_DOT_TOC_FILE);
   std::ofstream* dotTocStr = new std::ofstream;
   dotTocStr->open( dotTocFile.c_str(), ios::out|ios::binary );
   if ( !dotTocStr->good() )
   {
      delete dotRpfStr;
      dotRpfStr = 0;
      delete dotTocStr;
      dotTocStr =0;

      std::string e = MODULE;
      e += " ERROR:\nCould not open: ";
      e += dotTocFile.c_str();
      throw ossimException(e);
   }
   
   // Variables used throughout:
   ossimRefPtr<ossimProperty> prop = new ossimStringProperty();
   ossimString field;
   ossimString s;
   std::streampos fileHeaderLength = 0;
   std::streampos fileLength = 0;
      
   ossimRefPtr<ossimNitfFileHeaderV2_0> fileHdr = new ossimNitfFileHeaderV2_0();
   
   // Set the CLEVEL:
   s = "01";
   fileHdr->setComplexityLevel(s);
   
   // Set the OSTAID:
   prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::OSTAID_KW);
   fileHdr->setProperty(prop);
   
   // Set the FDT (date):
   fileHdr->setDate();
   
   // Set the FTITLE:
   s = "a.toc";
   fileHdr->setTitle(s);
   
   // Set the FSCLAS:
   prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::FSCLAS_KW);
   fileHdr->setProperty(prop);
   
   // Set the FSCODE:
   prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::FSCODE_KW);
   fileHdr->setProperty(prop);
   
   // Set the FSCTLH:
   prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::FSCTLH_KW);
   fileHdr->setProperty(prop);
   
   // Set the ONAME:
   prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::ONAME_KW);
   fileHdr->setProperty(prop);
   
   // Set the OPHONE:
   prop = sourceNitfFileHdr->getProperty(ossimNitfFileHeaderV2_X::OPHONE_KW);
   fileHdr->setProperty(prop);
   
   // Add the rpf header.
   ossimRpfHeader* rpfHdr = new ossimRpfHeader( *(sourceRpfHdr.get()) );
   
   ossimRefPtr<ossimNitfRegisteredTag> rpfHdrRp = rpfHdr;
   ossimNitfTagInformation rpfHdrInfo(rpfHdrRp);
   fileHdr->addTag(rpfHdrInfo);
   
   //---
   // Write it out...
   // The first write will be with an rpfheader with no location sections just
   // to see where the end of the file header is.
   //---
   fileHdr->writeStream(*dotTocStr);
   
   //---
   // End of file header. Get the header length. This will also be the
   // start of the location section.
   //---
   std::streampos pos = dotTocStr->tellp();
   std::streamoff locationSectionOffset = pos;
   
   // Set the header length:
   fileHdr->setHeaderLength( static_cast<ossim_uint64>(locationSectionOffset) );
   
   // Set the location of the location section.
   rpfHdr->setLocationSectionPos(locationSectionOffset);

   // Set the file name.
   rpfHdr->setFilename(A_DOT_TOC_FILE);
   
   // Add the component location records to the header.
   ossimRpfLocationSection* locSec = rpfHdr->getLocationSection();
   
   // Clear the records copied from the source a.toc.
   locSec->clearFields();
   
   //---
   // Set the length of the locSec to 74.  The record itself is 14 bytes plus
   // an additional 60 bytes for six location records ten bytes each.
   //---
   const ossim_uint16 LOCATION_SECTION_SIZE = 74;
   locSec->setLocationSectionLength(LOCATION_SECTION_SIZE);
   
   // Set the offset which 14 bytes to get to the first record.
   locSec->setLocationTableOffset(14);
   
   // Six records:
   locSec->setNumberOfComponentLocationRecords(6);
   
   // Each record 10 bytes:
   locSec->setLocationRecordLength(10);
   
   // Don't know the aggregate length yet.
   
   ossimRpfComponentLocationRecord locRec;
   
   // Note: See ossimRpfConstants for enum ossimRpfComponentId
   
   const ossim_uint32 RPFHDR_SIZE = 48;
   const ossim_uint32 LOCATION_SECTION_OFFSET = static_cast<ossim_uint32>(locationSectionOffset);
   const ossim_uint32 BOUNDARY_SUBHEADER_SIZE = 8;
   const ossim_uint32 BOUNDARY_RECORD_SIZE = 132;
   const ossim_uint32 FILE_SUBHEADER_SIZE = 13;
   // const ossim_uint32 = ;
   
   // Record 1 RPFHDR location:
   ossim_uint32 rpfHdrOffset = 0;
   if ( fileHdr->getTag(rpfHdrInfo, "RPFHDR") )
   {
      rpfHdrOffset = rpfHdrInfo.getTagDataOffset();
   }

   locRec.m_componentId = OSSIM_RPF_HEADER_COMPONENT; // 128
   locRec.m_componentLength = RPFHDR_SIZE;
   locRec.m_componentLocation = static_cast<ossim_uint32>(rpfHdrInfo.getTagDataOffset());
   locSec->addComponentRecord(locRec);

   if ( traceDebug() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG)<< "rpf hdr offset: " << rpfHdrOffset << "\n";
      locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) );
   }
   
   // Record 2 location section:
   locRec.m_componentId = OSSIM_RPF_LOCATION_COMPONENT; // 129
   locRec.m_componentLength = LOCATION_SECTION_SIZE;
   locRec.m_componentLocation = LOCATION_SECTION_OFFSET;
   locSec->addComponentRecord(locRec);

   if ( traceDebug() )
   {
      locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) );
   }
   
   // Record 3 boundary rect sub header section:
   locRec.m_componentId = OSSIM_RPF_BOUNDARY_RECT_SECTION_SUBHEADER; // 148
   locRec.m_componentLength = BOUNDARY_SUBHEADER_SIZE;
   locRec.m_componentLocation = locRec.m_componentLocation + LOCATION_SECTION_SIZE;
   locSec->addComponentRecord(locRec);

   if ( traceDebug() )
   {
      locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) );
   }
   
   // Capture the location.
   std::streamoff boundaryRectPosition = locRec.m_componentLocation;
   
   // Record 4 boundary rect table:
   locRec.m_componentId = OSSIM_RPF_BOUNDARY_RECT_TABLE; // 149
   locRec.m_componentLength = BOUNDARY_RECORD_SIZE;
   locRec.m_componentLocation = locRec.m_componentLocation + BOUNDARY_SUBHEADER_SIZE;
   locSec->addComponentRecord(locRec);

   if ( traceDebug() )
   {
      locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) );
   }
   
   // Record 5 file index sub header:
   locRec.m_componentId = OSSIM_RPF_FRAME_FILE_INDEX_SECTION_SUBHEADER; // 150
   locRec.m_componentLength = FILE_SUBHEADER_SIZE;
   locRec.m_componentLocation = locRec.m_componentLocation + BOUNDARY_RECORD_SIZE;
   locSec->addComponentRecord(locRec);

   if ( traceDebug() )
   {
      locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) );
   }
    
   // Record 6 file index sub header:
   locRec.m_componentId = OSSIM_RPF_FRAME_FILE_INDEX_SUBSECTION; // 151
   locRec.m_componentLength = 0;  // need to calculate.
   locRec.m_componentLocation = locRec.m_componentLocation + FILE_SUBHEADER_SIZE;
   locSec->addComponentRecord(locRec);

   if ( traceDebug() )
   {
      locRec.print( ossimNotify(ossimNotifyLevel_DEBUG) );
   }
   
   // Seek back and re-write...
   dotTocStr->seekp(0, ios::beg);
   fileHdr->writeStream(*dotTocStr);
   
   dotTocStr->seekp(boundaryRectPosition, ios::beg);

   // Only writing one entry:
   boundaryRectSectionSubheader->setNumberOfEntries(1);

   if ( traceDebug() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "writing boundaryRectSectionSubheader:\n" << *(boundaryRectSectionSubheader.get())
         << "\n";
   }

   //---
   // Write the boundary rectangle section.  This includes the subheader and subsection.
   // These coorespond to location records 3 and 4 above.
   //---
   boundaryRectSectionSubheader->writeStream(*dotTocStr);

   if ( traceDebug() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG) 
         << "Original boundaryRectTable:\n" << *(boundaryRectTable.get()) << "\n";
   }

   ossim_uint32 entry;
   if ( getCorespondingEntry( frameFileSubSection.get(), *dotRpfStr, entry ) )
   {
      ossimRpfBoundaryRectRecord boundaryRectRecord;
      if ( boundaryRectTable->getEntry( entry, boundaryRectRecord) )
      {
         if ( traceDebug() )
         {
            ossimNotify(ossimNotifyLevel_DEBUG) 
               << "writing boundaryRectTable:\n" << boundaryRectRecord << "\n";
         }
         
         boundaryRectRecord.writeStream(*dotTocStr);
      }
      else
      {
         std::string e = MODULE;
         e += " ERROR:\nCould not get bounding rect record for entry: ";
         e += ossimString::toString(entry).c_str();
         throw ossimException(e);
      }
   }
   else
   {
      std::string e = MODULE;
      e += " ERROR:\nCould not deduce entry from frame list!";
      throw ossimException(e);
   }

   frameFileSubHeader->setNumberOfIndexRecords( getNumberOfFrames(*dotRpfStr) );
   frameFileSubHeader->setNumberOfPathnameRecords(1);
   const ossim_uint16 FRAME_FILE_INDEX_RECORD_LENGTH = 33;
   frameFileSubHeader->setIndexRecordLength( FRAME_FILE_INDEX_RECORD_LENGTH );

   if ( traceDebug() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "writing frameFileSubHeader:\n" << *(frameFileSubHeader.get()) << "\n";
   }
   frameFileSubHeader->writeStream( *dotTocStr );

   if ( traceDebug() )
   {
      ossimNotify(ossimNotifyLevel_DEBUG) << "writing frameFileSubSection:\n";
   }

   std::streamoff frameFileIndexSectionStartPos = dotTocStr->tellp();
   
   writeFrameFileIndexSection(frameFileSubSection.get(), *dotRpfStr, *dotTocStr);
   
   std::streamoff endOfFilePos = dotTocStr->tellp();

   // Update the location section length for the frame file index section.
   locSec->getLocationRecordList()[5].m_componentLength =
      static_cast<ossim_uint32>(endOfFilePos - frameFileIndexSectionStartPos);

   // Update the length of all location sections.
   locSec->setComponentAggregateLength(
      static_cast<ossim_uint32>(endOfFilePos) - rpfHdr->getLocationSectionLocation() );
   

   fileHdr->setFileLength(static_cast<ossim_uint64>(endOfFilePos));
   dotTocStr->seekp(0, ios::beg);
   fileHdr->writeStream(*dotTocStr);

   ossimNotify(ossimNotifyLevel_DEBUG) << "Wrote file: " << dotTocFile << "\n";

   // Copy the frames to the output directory.
   copyFrames(*dotRpfStr, outputDir);

   // Cleanup:
   delete dotRpfStr;
   dotRpfStr = 0;
   delete dotTocStr;
   dotTocStr =0;
}
コード例 #4
0
int AudioDecoderMediaFoundation::read(int size, const SAMPLE *destination)
{
	assert(size < sizeof(m_destBufferShort));
    if (sDebug) { std::cout << "read() " << size << std::endl; }
	//TODO: Change this up if we want to support just short samples again -- Albert
    SHORT_SAMPLE *destBuffer = m_destBufferShort;
	size_t framesRequested(size / m_iChannels);
    size_t framesNeeded(framesRequested);

    // first, copy frames from leftover buffer IF the leftover buffer is at
    // the correct frame
    if (m_leftoverBufferLength > 0 && m_leftoverBufferPosition == m_nextFrame) {
        copyFrames(destBuffer, &framesNeeded, m_leftoverBuffer,
            m_leftoverBufferLength);
        if (m_leftoverBufferLength > 0) {
            if (framesNeeded != 0) {
                std::cerr << __FILE__ << __LINE__
                           << "WARNING: Expected frames needed to be 0. Abandoning this file.";
                m_dead = true;
            }
            m_leftoverBufferPosition += framesRequested;
        }
    } else {
        // leftoverBuffer already empty or in the wrong position, clear it
        m_leftoverBufferLength = 0;
    }

    while (!m_dead && framesNeeded > 0) {
        HRESULT hr(S_OK);
        DWORD dwFlags(0);
        __int64 timestamp(0);
        IMFSample *pSample(NULL);
        bool error(false); // set to true to break after releasing

        hr = m_pReader->ReadSample(
            MF_SOURCE_READER_FIRST_AUDIO_STREAM, // [in] DWORD dwStreamIndex,
            0,                                   // [in] DWORD dwControlFlags,
            NULL,                                // [out] DWORD *pdwActualStreamIndex,
            &dwFlags,                            // [out] DWORD *pdwStreamFlags,
            &timestamp,                          // [out] LONGLONG *pllTimestamp,
            &pSample);                           // [out] IMFSample **ppSample
        if (FAILED(hr)) {
            if (sDebug) { std::cout << "ReadSample failed." << std::endl; }
            break;
        }

        if (sDebug) {
            std::cout << "ReadSample timestamp: " << timestamp
                     << "frame: " << frameFromMF(timestamp)
                     << "dwflags: " << dwFlags
					 << std::endl;
        }

        if (dwFlags & MF_SOURCE_READERF_ERROR) {
            // our source reader is now dead, according to the docs
            std::cerr << "SSMF: ReadSample set ERROR, SourceReader is now dead";
            m_dead = true;
            break;
        } else if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM) {
            std::cout << "SSMF: End of input file." << std::endl;
            break;
        } else if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) {
            std::cerr << "SSMF: Type change";
            break;
        } else if (pSample == NULL) {
            // generally this will happen when dwFlags contains ENDOFSTREAM,
            // so it'll be caught before now -bkgood
            std::cerr << "SSMF: No sample";
            continue;
        } // we now own a ref to the instance at pSample

        IMFMediaBuffer *pMBuffer(NULL);
        // I know this does at least a memcopy and maybe a malloc, if we have
        // xrun issues with this we might want to look into using
        // IMFSample::GetBufferByIndex (although MS doesn't recommend this)
        if (FAILED(hr = pSample->ConvertToContiguousBuffer(&pMBuffer))) {
            error = true;
            goto releaseSample;
        }
        short *buffer(NULL);
        size_t bufferLength(0);
        hr = pMBuffer->Lock(reinterpret_cast<unsigned __int8**>(&buffer), NULL,
            reinterpret_cast<DWORD*>(&bufferLength));
        if (FAILED(hr)) {
            error = true;
            goto releaseMBuffer;
        }
        bufferLength /= (m_iBitsPerSample / 8 * m_iChannels); // now in frames

        if (m_seeking) {
            __int64 bufferPosition(frameFromMF(timestamp));
            if (sDebug) {
                std::cout << "While seeking to "
                         << m_nextFrame << "WMF put us at " << bufferPosition
						 << std::endl;

            }
            if (m_nextFrame < bufferPosition) {
                // Uh oh. We are farther forward than our seek target. Emit
                // silence? We can't seek backwards here.
                SHORT_SAMPLE* pBufferCurpos = destBuffer +
                        (size - framesNeeded * m_iChannels);
                __int64 offshootFrames = bufferPosition - m_nextFrame;

                // If we can correct this immediately, write zeros and adjust
                // m_nextFrame to pretend it never happened.

                if (offshootFrames <= framesNeeded) {
                    std::cerr << __FILE__ << __LINE__
                               << "Working around inaccurate seeking. Writing silence for"
                               << offshootFrames << "frames";
                    // Set offshootFrames * m_iChannels samples to zero.
                    memset(pBufferCurpos, 0,
                           sizeof(*pBufferCurpos) * offshootFrames *
                           m_iChannels);
                    // Now m_nextFrame == bufferPosition
                    m_nextFrame += offshootFrames;
                    framesNeeded -= offshootFrames;
                } else {
                    // It's more complicated. The buffer we have just decoded is
                    // more than framesNeeded frames away from us. It's too hard
                    // for us to handle this correctly currently, so let's just
                    // try to get on with our lives.
                    m_seeking = false;
                    m_nextFrame = bufferPosition;
                    std::cerr << __FILE__ << __LINE__
                               << "Seek offshoot is too drastic. Cutting losses and pretending the current decoded audio buffer is the right seek point.";
                }
            }

            if (m_nextFrame >= bufferPosition &&
                m_nextFrame < bufferPosition + bufferLength) {
                // m_nextFrame is in this buffer.
                buffer += (m_nextFrame - bufferPosition) * m_iChannels;
                bufferLength -= m_nextFrame - bufferPosition;
                m_seeking = false;
            } else {
                // we need to keep going forward
                goto releaseRawBuffer;
            }
        }

        // If the bufferLength is larger than the leftover buffer, re-allocate
        // it with 2x the space.
        if (bufferLength * m_iChannels > m_leftoverBufferSize) {
            int newSize = m_leftoverBufferSize;

            while (newSize < bufferLength * m_iChannels) {
                newSize *= 2;
            }
            SHORT_SAMPLE* newBuffer = new SHORT_SAMPLE[newSize];
            memcpy(newBuffer, m_leftoverBuffer,
                   sizeof(m_leftoverBuffer[0]) * m_leftoverBufferSize);
            delete [] m_leftoverBuffer;
            m_leftoverBuffer = newBuffer;
            m_leftoverBufferSize = newSize;
        }
        copyFrames(destBuffer + (size - framesNeeded * m_iChannels),
            &framesNeeded, buffer, bufferLength);

releaseRawBuffer:
        hr = pMBuffer->Unlock();
        // I'm ignoring this, MSDN for IMFMediaBuffer::Unlock stipulates
        // nothing about the state of the instance if this fails so might as
        // well just let it be released.
        //if (FAILED(hr)) break;
releaseMBuffer:
        safeRelease(&pMBuffer);
releaseSample:
        safeRelease(&pSample);
        if (error) break;
    }

    m_nextFrame += framesRequested - framesNeeded;
    if (m_leftoverBufferLength > 0) {
        if (framesNeeded != 0) {
            std::cerr << __FILE__ << __LINE__
				<< "WARNING: Expected frames needed to be 0. Abandoning this file." << std::endl;
            m_dead = true;
        }
        m_leftoverBufferPosition = m_nextFrame;
    }
    long samples_read = size - framesNeeded * m_iChannels;
    m_iCurrentPosition += samples_read;
    if (sDebug) { std::cout << "read() " << size << " returning " << samples_read << std::endl; }
	
	const int sampleMax = 1 << (m_iBitsPerSample-1);
	//Convert to float samples
	if (m_iChannels == 2)
	{
		SAMPLE *destBufferFloat(const_cast<SAMPLE*>(destination));
		for (unsigned long i = 0; i < samples_read; i++)
		{
			destBufferFloat[i] = destBuffer[i] / (float)sampleMax;
		}
	}
	else //Assuming mono, duplicate into stereo frames...
	{
		SAMPLE *destBufferFloat(const_cast<SAMPLE*>(destination));
		for (unsigned long i = 0; i < samples_read; i++)
		{
			destBufferFloat[i] = destBuffer[i] / (float)sampleMax;
		}
	}
    return samples_read;
}