void _mp4v2_write_chapters(MP4V2Handles *handle) { VALUE self = handle->self; MP4FileHandle mp4v2 = handle->file; VALUE chapters = rb_check_array_type(GET(chapters)), chapter, title; double last_stamp = 0, stamp; MP4Chapter_t *chaps; uint32_t count = 0; switch(TYPE(chapters)) { case T_ARRAY: RARRAY_ALL_INSTANCE(chapters, rb_cChapter, chapter); // Make chapters go in order of timestamp rb_ary_sort_bang(chapters); count = RARRAY_LEN(chapters); chaps = handle->chapters = (MP4Chapter_t *)malloc(sizeof(MP4Chapter_t) * count); if (!chaps) { rb_raise(rb_eNoMemError, "unable to save all changes to file"); } for (uint32_t i = 0; i < count; i++) { // Calculate the duration of chapter from previous timestamp and current chapter = rb_ary_entry(chapters, i); stamp = NUM2DBL(rb_funcall(rb_ivar_get(chapter, rb_intern("@timestamp")), rb_intern("milliseconds"), 0)); chaps[i].duration = stamp - last_stamp; last_stamp = stamp; // Get the title of the chapter title = rb_encode_utf8(rb_ivar_get(chapter, rb_intern("@title"))); if (RSTRING_LEN(title) > MP4V2_CHAPTER_TITLE_MAX) { rb_raise(rb_eStandardError, "chapter title '%s' is too long, it should be at most %d bytes", RSTRING_PTR(title), MP4V2_CHAPTER_TITLE_MAX); } memcpy(chaps[i].title, RSTRING_PTR(title), RSTRING_LEN(title)+1); } if (count > 0) { MP4SetChapters(mp4v2, chaps, count, MP4ChapterTypeAny); } else { MP4DeleteChapters(mp4v2, MP4ChapterTypeAny); } free(chaps); handle->chapters = NULL; break; case T_NIL: MP4DeleteChapters(mp4v2, MP4ChapterTypeAny); break; default:; } }
/** Action for removing 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::actionRemove( JobContext& job ) { ostringstream oss; oss << "Deleting " << getChapterTypeName( _ChapterType ) << " chapters from file " << '"' << job.file << '"' << endl; verbose1f( "%s", oss.str().c_str() ); if( dryrunAbort() ) { return SUCCESS; } job.fileHandle = MP4Modify( job.file.c_str() ); if( job.fileHandle == MP4_INVALID_FILE_HANDLE ) { return herrf( "unable to open for write: %s\n", job.file.c_str() ); } MP4ChapterType chtp = MP4DeleteChapters( job.fileHandle, _ChapterType ); if( MP4ChapterTypeNone == chtp ) { return FAILURE; } fixQtScale( job.fileHandle ); job.optimizeApplicable = true; return SUCCESS; }