Skip to content

Commit

Permalink
Add methods for manual flushing and changing write offset
Browse files Browse the repository at this point in the history
Use case - generating fragmented MP4s for HLS streaming requires
creating an initialization segment with decoder-specific config
(the moov box). Manual flush allows writing out the moov box
before adding samples.

Similar with write offset - after writing the moov box, one wants
to write media segments that begin with a moof box and have 1 or more
mdat boxes. This adds a method for overwriting the write offset,
in case the library user wants to treat MP4E_mux_t as an opaque type.
  • Loading branch information
jprjr committed Apr 23, 2022
1 parent 4575afb commit fddfeaa
Showing 1 changed file with 38 additions and 1 deletion.
39 changes: 38 additions & 1 deletion minimp4.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,18 @@ int MP4E_add_track(MP4E_mux_t *mux, const MP4E_track_t *track_data);
*/
int MP4E_put_sample(MP4E_mux_t *mux, int track_num, const void *data, int data_bytes, int duration, int kind);

/**
* Writes the MP4 index if not already written, and any pending track data
*
* return error code MP4E_STATUS_*
*/
int MP4E_flush(MP4E_mux_t *mux);

/**
* Set the file position for the next write operation
*/
void MP4E_set_write_pos(MP4E_mux_t *mux, int64_t write_pos);

/**
* Finalize MP4 file, de-allocated memory, and closes MP4 multiplexer.
* The close operation takes a time and disk space, since it writes MP4 file
Expand Down Expand Up @@ -696,6 +708,7 @@ typedef struct MP4E_mux_tag
int sequential_mode_flag;
int enable_fragmentation; // flag, indicating streaming-friendly 'fragmentation' mode
int fragments_count; // # of fragments in 'fragmentation' mode
int index_flushed; // flag, indicating if the index has been written

} MP4E_mux_t;

Expand Down Expand Up @@ -817,6 +830,7 @@ MP4E_mux_t *MP4E_open(int sequential_mode_flag, int enable_fragmentation, void *
mux->sequential_mode_flag = sequential_mode_flag || enable_fragmentation;
mux->enable_fragmentation = enable_fragmentation;
mux->fragments_count = 0;
mux->index_flushed = 0;
mux->write_callback = write_callback;
mux->token = token;
mux->text_comment = NULL;
Expand Down Expand Up @@ -1108,8 +1122,10 @@ int MP4E_put_sample(MP4E_mux_t *mux, int track_num, const void *data, int data_b
// NOTE: assume a constant `duration` to calculate current timestamp
uint64_t timestamp = (uint64_t)mux->fragments_count * duration;
#endif
if (!mux->fragments_count++)
if (!mux->index_flushed) {
ERR(mp4e_flush_index(mux)); // write file headers before 1st sample
mux->index_flushed = 1;
}
// write MOOF + MDAT + sample data
#if MP4D_TFDT_SUPPORT
ERR(mp4e_write_fragment_header(mux, track_num, data_bytes, duration, kind, timestamp));
Expand Down Expand Up @@ -1739,6 +1755,27 @@ static int mp4e_flush_index(MP4E_mux_t *mux)
return err;
}

int MP4E_flush(MP4E_mux_t *mux) {
unsigned int ntr, ntracks = mux->tracks.bytes / sizeof(track_t);

if (!mux->index_flushed) {
ERR(mp4e_flush_index(mux));
mux->index_flushed = 1;
}

for (ntr = 0; ntr < ntracks; ntr++)
{
track_t *tr = ((track_t*)mux->tracks.data) + ntr;
ERR(write_pending_data(mux, tr));
}

return MP4E_STATUS_OK;
}

void MP4E_set_write_pos(MP4E_mux_t *mux, int64_t write_pos) {
mux->write_pos = write_pos;
}

int MP4E_close(MP4E_mux_t *mux)
{
int err = MP4E_STATUS_OK;
Expand Down

0 comments on commit fddfeaa

Please sign in to comment.