int mk_startFrame(mk_Writer *w) { if (mk_flushFrame(w) < 0) return -1; w->in_frame = 1; w->keyframe = 0; return 0; }
int mk_startFrame(mk_Writer *w, mk_Track *track) { if (mk_flushFrame(w, track) < 0) return -1; track->in_frame = 1; track->frame.keyframe = 0; track->frame.lacing = MK_LACING_NONE; track->frame.lacing_num_frames = 0; track->frame.lacing_sizes = NULL; return 0; }
int mk_close(mk_Writer *w) { int ret = 0; if (mk_flushFrame(w) < 0 || mk_closeCluster(w) < 0) ret = -1; if (w->wrote_header) { fseek(w->fp, w->duration_ptr, SEEK_SET); if (mk_writeFloatRaw(w->root, (float)((double)(w->max_frame_tc+w->def_duration) / w->timescale)) < 0 || mk_flushContextData(w->root) < 0) ret = -1; } mk_destroyContexts(w); fclose(w->fp); free(w); return ret; }
int mk_close(mk_Writer *w) { int i, ret = 0; mk_Track *tk; int64_t max_frame_tc = w->tracks_arr[0]->max_frame_tc; uint64_t segment_size = 0; unsigned char c_size[8]; unsigned char segment_uid[16]; md5_finish(&w->segment_md5, segment_uid); for (i = w->num_tracks - 1; i >= 0; i--) { tk = w->tracks_arr[i]; if (mk_flushFrame(w, tk) < 0) ret = -1; } if (mk_closeCluster(w) < 0) ret = -1; w->seek_data.cues = w->f_pos - w->segment_ptr; if (mk_closeContext(w->cues, 0) < 0) ret = -1; if (mk_flushContextData(w->root) < 0) ret = -1; if (w->cluster.seekhead) { w->seek_data.seekhead = w->f_pos - w->segment_ptr; if (mk_closeContext(w->cluster.seekhead, 0) < 0) ret = -1; if (mk_flushContextData(w->root) < 0) ret = -1; } if (w->attachments != NULL) { w->seek_data.attachments = w->f_pos - w->segment_ptr; mk_writeAttachments(w); if (mk_flushContextData(w->root) < 0) ret = -1; } if (w->tags != NULL) { w->seek_data.tags = w->f_pos - w->segment_ptr; mk_writeTags(w); if (mk_flushContextData(w->root) < 0) ret = -1; } if (w->chapters != NULL) { if (w->vlc_compat) { if (mk_flushContextData(w->root) < 0) ret = -1; if (mk_seekFile(w, w->segment_ptr + RESERVED_SEEKHEAD + 3) < 0) ret = -1; } w->seek_data.chapters = w->f_pos - w->segment_ptr; mk_writeChapters(w); if (mk_flushContextData(w->root) < 0) ret = -1; if (w->vlc_compat) { if (mk_writeVoid(w->root, (RESERVED_CHAPTERS - (w->f_pos - w->segment_ptr - RESERVED_SEEKHEAD - 3))) < 0) ret = -1; if (mk_flushContextData(w->root) < 0) ret = -1; } } if (w->wrote_header) { if (w->vlc_compat) { if (mk_seekFile(w, w->segment_ptr) < 0) ret = -1; } if (mk_writeSeekHead(w, &w->seek_data.seekhead) < 0) ret = -1; w->seek_data.seekhead -= w->segment_ptr; if (w->vlc_compat) { if (mk_flushContextData(w->root) < 0) ret = -1; if (mk_writeVoid(w->root, (RESERVED_SEEKHEAD - (w->f_pos - w->segment_ptr))) < 0) ret = -1; } if (mk_flushContextData(w->root) < 0) ret = -1; if (!w->vlc_compat) { int i = w->seek_data.segmentinfo; w->seek_data.segmentinfo = 0; w->seek_data.tracks = 0; w->seek_data.cues = 0; w->seek_data.chapters = 0; w->seek_data.attachments = 0; w->seek_data.tags = 0; if (mk_seekFile(w, w->segment_ptr) < 0) ret = -1; if (mk_writeSeekHead(w, NULL) < 0 || mk_flushContextData(w->root) < 0) ret = -1; // The conditional below is easier to understand, but incorrect // because f_pos is unsigned and causes the lhs to be evaluated // as an unsigned quantity. // if (((i + w->segment_ptr) - w->f_pos - 2) > 1) if ((i + w->segment_ptr) > (w->f_pos + 3)) if (mk_writeVoid(w->root, (i + w->segment_ptr) - w->f_pos - 2) < 0 || mk_flushContextData(w->root) < 0) ret = -1; } if (mk_seekFile(w, w->duration_ptr) < 0) ret = -1; if (mk_writeFloatRaw(w->root, (float) ((double) (max_frame_tc + w->def_duration) / w->timescale)) < 0 || mk_flushContextData(w->root) < 0) ret = -1; if (mk_seekFile(w, w->segment_ptr - 8) < 0) ret = -1; segment_size = w->f_eof - w->segment_ptr; for (i = 7; i > 0; --i) c_size[i] = segment_size >> (8 * (7 - i)); c_size[i] = 0x01; if (mk_appendContextData(w->root, &c_size, 8) < 0 || mk_flushContextData(w->root) < 0) ret = -1; if (mk_seekFile(w, w->segmentuid_ptr) < 0) ret = -1; if (mk_writeBin(w->root, MATROSKA_ID_SEGMENTUID, segment_uid, sizeof(segment_uid)) < 0 || mk_flushContextData(w->root) < 0) ret = -1; } /* update any track private data that may have changed */ for (i = w->num_tracks - 1; i >= 0; i--) { tk = w->tracks_arr[i]; if (tk->private_data_size && tk->private_data) { if (mk_seekFile(w, tk->private_data_ptr) < 0) ret = -1; if (mk_writeBin(w->root, MATROSKA_ID_CODECPRIVATE, tk->private_data, tk->private_data_size) < 0 || mk_flushContextData(w->root) < 0) ret = -1; free(tk->private_data); } w->tracks_arr[i] = NULL; --w->num_tracks; free(tk); } if (mk_closeContext(w->root, 0) < 0) ret = -1; mk_destroyContexts(w); fclose(w->fp); free(w->tracks_arr); free(w); return ret; }
static int MKVMux(hb_mux_object_t *m, hb_mux_data_t *mux_data, hb_buffer_t *buf) { char chapter_name[1024]; hb_chapter_t *chapter_data; uint64_t timecode = 0; ogg_packet *op = NULL; hb_job_t *job = m->job; if (mux_data == job->mux_data) { /* Video */ timecode = buf->s.start * TIMECODE_SCALE; if (job->chapter_markers && buf->s.new_chap) { // reached chapter N, write marker for chapter N-1 mux_data->current_chapter = buf->s.new_chap - 1; // chapter numbers start at 1, but the list starts at 0 chapter_data = hb_list_item(job->list_chapter, mux_data->current_chapter - 1); // make sure we're not writing a chapter that has 0 length if (chapter_data != NULL && mux_data->prev_chapter_tc < timecode) { if (chapter_data->title != NULL) { snprintf(chapter_name, 1023, "%s", chapter_data->title); } else { snprintf(chapter_name, 1023, "Chapter %d", mux_data->current_chapter); } mk_createChapterSimple(m->file, mux_data->prev_chapter_tc, mux_data->prev_chapter_tc, chapter_name); } mux_data->prev_chapter_tc = timecode; } if (job->vcodec == HB_VCODEC_THEORA) { /* ughhh, theora is a pain :( */ op = (ogg_packet *)buf->data; op->packet = buf->data + sizeof( ogg_packet ); if (mk_startFrame(m->file, mux_data->track) < 0) { hb_error( "Failed to write frame to output file, Disk Full?" ); *job->die = 1; } mk_addFrameData(m->file, mux_data->track, op->packet, op->bytes); mk_setFrameFlags(m->file, mux_data->track, timecode, 1, 0); hb_buffer_close( &buf ); return 0; } } else if (mux_data->subtitle) { if( mk_startFrame(m->file, mux_data->track) < 0) { hb_error("Failed to write frame to output file, Disk Full?"); *job->die = 1; } uint64_t duration; timecode = buf->s.start * TIMECODE_SCALE; if (buf->s.stop <= buf->s.start) { duration = 0; } else { duration = buf->s.stop * TIMECODE_SCALE - timecode; } mk_addFrameData(m->file, mux_data->track, buf->data, buf->size); mk_setFrameFlags(m->file, mux_data->track, timecode, 1, duration); mk_flushFrame(m->file, mux_data->track); hb_buffer_close(&buf); return 0; } else { /* Audio */ timecode = buf->s.start * TIMECODE_SCALE; if (mux_data->codec == HB_ACODEC_VORBIS) { /* ughhh, vorbis is a pain :( */ op = (ogg_packet *)buf->data; op->packet = buf->data + sizeof( ogg_packet ); if (mk_startFrame(m->file, mux_data->track)) { hb_error( "Failed to write frame to output file, Disk Full?" ); *job->die = 1; } mk_addFrameData(m->file, mux_data->track, op->packet, op->bytes); mk_setFrameFlags(m->file, mux_data->track, timecode, 1, 0); hb_buffer_close( &buf ); return 0; } } if( mk_startFrame(m->file, mux_data->track) < 0) { hb_error( "Failed to write frame to output file, Disk Full?" ); *job->die = 1; } mk_addFrameData(m->file, mux_data->track, buf->data, buf->size); mk_setFrameFlags(m->file, mux_data->track, timecode, (((job->vcodec == HB_VCODEC_X264 || (job->vcodec & HB_VCODEC_FFMPEG_MASK)) && mux_data == job->mux_data) ? (buf->s.frametype == HB_FRAME_IDR) : ((buf->s.frametype & HB_FRAME_KEY) != 0)), 0 ); hb_buffer_close( &buf ); return 0; }