示例#1
0
void _mp4v2_read_chapters(MP4V2Handles *handle) {
  VALUE self = handle->self;
  MP4Chapter_t *chaps = NULL;
  uint32_t count;

  MP4GetChapters(handle->file, &chaps, &count, MP4ChapterTypeAny);

  VALUE chapters = rb_ary_new2(count), chapter;

  MP4Duration sum = 0;
  for (uint32_t i = 0; i < count; i++) {
    chapter = rb_funcall(rb_cChapter, rb_intern("new"), 2, DBL2NUM(sum), rb_utf8_str(chaps[i].title));
    rb_ary_push(chapters, chapter);
    sum += chaps[i].duration;
  }

  free(chaps);
  handle->chapters = NULL;

  SET(chapters, chapters);
}
示例#2
0
/** Action for exporting chapters from the <b>job.file</b>
 *
 *  
 *  @param job the job to process
 *  @return mp4v2::util::SUCCESS if successful, mp4v2::util::FAILURE otherwise
 */
bool
ChapterUtility::actionExport( JobContext& job )
{
    job.fileHandle = MP4Read( job.file.c_str() );
    if( job.fileHandle == MP4_INVALID_FILE_HANDLE )
    {
        return herrf( "unable to open for read: %s\n", job.file.c_str() );
    }

    // get the list of chapters
    MP4Chapter_t*  chapters = 0;
    uint32_t       chapterCount = 0;
    MP4ChapterType chtp = MP4GetChapters( job.fileHandle, &chapters, &chapterCount, _ChapterType );
    if (0 == chapterCount)
    {
        return herrf( "File \"%s\" does not contain chapters of type %s\n", job.file.c_str(),
                      getChapterTypeName( chtp ).c_str() );
    }

    // build the filename
    string outName = job.file;
    if( _ChapterFile.empty() )
    {
        FileSystem::pathnameStripExtension( outName );
        outName.append( ".chapters.txt" );
    }
    else
    {
        outName = _ChapterFile;
    }

    ostringstream oss;
    oss << "Exporting " << chapterCount << " " << getChapterTypeName( chtp );
    oss << " chapters from file " << '"' << job.file << '"' << " into chapter file " << '"' << outName << '"' << endl;

    verbose1f( "%s", oss.str().c_str() );
    if( dryrunAbort() )
    {
        // free up the memory
        MP4Free(chapters);

        return SUCCESS;
    }

    // open the file
    File out( outName, File::MODE_CREATE );
    if( openFileForWriting( out ) )
    {
        // free up the memory
        MP4Free(chapters);

        return FAILURE;
    }

    // write the chapters
#if defined( _WIN32 )
    static const char* LINEND = "\r\n";
#else
    static const char* LINEND = "\n";
#endif
    File::Size nout;
    bool failure = SUCCESS;
    int width = 2;
    if( CHPT_FMT_COMMON == _ChapterFormat && (chapterCount / 100) >= 1 )
    {
        width = 3;
    }
    Timecode duration( 0, CHAPTERTIMESCALE );
    duration.setFormat( Timecode::DECIMAL );
    for( uint32_t i = 0; i < chapterCount; ++i )
    {
        // print the infos
        ostringstream oss;
        switch( _ChapterFormat )
        {
            case CHPT_FMT_COMMON:
                oss << "CHAPTER" << setw( width ) << setfill( '0' ) << i+1 <<     '=' << duration.svalue << LINEND
                    << "CHAPTER" << setw( width ) << setfill( '0' ) << i+1 << "NAME=" << chapters[i].title << LINEND;
                break;
            case CHPT_FMT_NATIVE:
            default:
                oss << duration.svalue << ' ' << chapters[i].title << LINEND;
        }

        string str = oss.str();
        if( out.write( str.c_str(), str.size(), nout ) )
        {
            failure = herrf( "write to %s failed: %s\n", outName.c_str(), sys::getLastErrorStr() );
            break;
        }

        // add the duration of this chapter to the sum (the start time of the next chapter)
        duration += Timecode(chapters[i].duration, CHAPTERTIMESCALE);
    }
    out.close();
    if( failure )
    {
        verbose1f( "removing file %s\n", outName.c_str() );
        ::remove( outName.c_str() );
    }

    // free up the memory
    MP4Free(chapters);

    return SUCCESS;
}