vod_status_t dash_packager_build_fragment_header( request_context_t* request_context, media_set_t* media_set, uint32_t segment_index, uint32_t sample_description_index, dash_fragment_header_extensions_t* extensions, bool_t size_only, vod_str_t* result, size_t* total_fragment_size) { media_sequence_t* sequence = &media_set->sequences[0]; media_track_t* first_track = sequence->filtered_clips[0].first_track; uint64_t earliest_pres_time = dash_packager_get_earliest_pres_time(media_set, first_track); sidx_params_t sidx_params; size_t first_frame_offset; size_t mdat_atom_size; size_t trun_atom_size; size_t tfhd_atom_size; size_t moof_atom_size; size_t traf_atom_size; size_t result_size; u_char* p; // calculate sizes dash_packager_init_sidx_params(media_set, sequence, &sidx_params); mdat_atom_size = ATOM_HEADER_SIZE + sequence->total_frame_size; if (extensions->mdat_prefix_writer != NULL) { mdat_atom_size += extensions->mdat_prefix_writer->atom_size; } trun_atom_size = mp4_builder_get_trun_atom_size(first_track->media_info.media_type, sequence->total_frame_count); tfhd_atom_size = ATOM_HEADER_SIZE + sizeof(tfhd_atom_t); if (sample_description_index > 0) { tfhd_atom_size += sizeof(uint32_t); } traf_atom_size = ATOM_HEADER_SIZE + tfhd_atom_size + ATOM_HEADER_SIZE + (earliest_pres_time > UINT_MAX ? sizeof(tfdt64_atom_t) : sizeof(tfdt_atom_t)) + trun_atom_size + extensions->extra_traf_atoms_size; moof_atom_size = ATOM_HEADER_SIZE + ATOM_HEADER_SIZE + sizeof(mfhd_atom_t)+ traf_atom_size; *total_fragment_size = sizeof(styp_atom) + ATOM_HEADER_SIZE + (sidx_params.earliest_pres_time > UINT_MAX ? sizeof(sidx64_atom_t) : sizeof(sidx_atom_t)) + moof_atom_size + mdat_atom_size; result_size = *total_fragment_size - sequence->total_frame_size; // head request optimization if (size_only) { return VOD_OK; } // allocate the buffer p = vod_alloc(request_context->pool, result_size); if (p == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "dash_packager_build_fragment_header: vod_alloc failed"); return VOD_ALLOC_FAILED; } result->data = p; // styp p = vod_copy(p, styp_atom, sizeof(styp_atom)); // sidx if (sidx_params.earliest_pres_time > UINT_MAX) { p = dash_packager_write_sidx64_atom(p, &sidx_params, moof_atom_size + mdat_atom_size); } else { p = dash_packager_write_sidx_atom(p, &sidx_params, moof_atom_size + mdat_atom_size); } // moof write_atom_header(p, moof_atom_size, 'm', 'o', 'o', 'f'); // moof.mfhd p = mp4_builder_write_mfhd_atom(p, segment_index); // moof.traf write_atom_header(p, traf_atom_size, 't', 'r', 'a', 'f'); // moof.traf.tfhd p = dash_packager_write_tfhd_atom(p, first_track->media_info.track_id, sample_description_index); // moof.traf.tfdt if (earliest_pres_time > UINT_MAX) { p = dash_packager_write_tfdt64_atom(p, earliest_pres_time); } else { p = dash_packager_write_tfdt_atom(p, (uint32_t)earliest_pres_time); } // moof.traf.trun first_frame_offset = moof_atom_size + ATOM_HEADER_SIZE; if (extensions->mdat_prefix_writer != NULL) { first_frame_offset += extensions->mdat_prefix_writer->atom_size; } p = mp4_builder_write_trun_atom( p, sequence, first_frame_offset); // moof.traf.xxx if (extensions->write_extra_traf_atoms_callback != NULL) { p = extensions->write_extra_traf_atoms_callback(extensions->write_extra_traf_atoms_context, p, moof_atom_size + ATOM_HEADER_SIZE); } // mdat write_atom_header(p, mdat_atom_size, 'm', 'd', 'a', 't'); // mdat prefix if (extensions->mdat_prefix_writer != NULL) { p = extensions->mdat_prefix_writer->write(extensions->mdat_prefix_writer->context, p); } result->len = p - result->data; if (result->len != result_size) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "dash_packager_build_fragment_header: result length %uz exceeded allocated length %uz", result->len, result_size); return VOD_UNEXPECTED; } return VOD_OK; }
vod_status_t dash_packager_build_fragment_header( request_context_t* request_context, mpeg_stream_metadata_t* stream_metadata, uint32_t segment_index, uint32_t sample_description_index, size_t extra_traf_atoms_size, write_extra_traf_atoms_callback_t write_extra_traf_atoms_callback, void* write_extra_traf_atoms_context, atom_writer_t* mdat_prefix_writer, bool_t size_only, vod_str_t* result, size_t* total_fragment_size) { uint64_t earliest_pres_time = dash_packager_get_earliest_pres_time(stream_metadata); size_t first_frame_offset; size_t mdat_atom_size; size_t trun_atom_size; size_t tfhd_atom_size; size_t moof_atom_size; size_t traf_atom_size; size_t result_size; u_char* p; // calculate sizes mdat_atom_size = ATOM_HEADER_SIZE + stream_metadata->total_frames_size; if (mdat_prefix_writer != NULL) { mdat_atom_size += mdat_prefix_writer->atom_size; } trun_atom_size = mp4_builder_get_trun_atom_size(stream_metadata->media_info.media_type, stream_metadata->frame_count); tfhd_atom_size = ATOM_HEADER_SIZE + sizeof(tfhd_atom_t); if (sample_description_index > 0) { tfhd_atom_size += sizeof(uint32_t); } traf_atom_size = ATOM_HEADER_SIZE + tfhd_atom_size + ATOM_HEADER_SIZE + (earliest_pres_time > UINT_MAX ? sizeof(tfdt64_atom_t) : sizeof(tfdt_atom_t)) + trun_atom_size + extra_traf_atoms_size; moof_atom_size = ATOM_HEADER_SIZE + ATOM_HEADER_SIZE + sizeof(mfhd_atom_t)+ traf_atom_size; result_size = sizeof(styp_atom)+ ATOM_HEADER_SIZE + (earliest_pres_time > UINT_MAX ? sizeof(sidx64_atom_t) : sizeof(sidx_atom_t)) + moof_atom_size + mdat_atom_size - stream_metadata->total_frames_size; // mdat *total_fragment_size = result_size + stream_metadata->total_frames_size; // head request optimization if (size_only) { return VOD_OK; } // allocate the buffer result->data = vod_alloc(request_context->pool, result_size); if (result->data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "dash_packager_build_fragment_header: vod_alloc failed"); return VOD_ALLOC_FAILED; } // styp p = vod_copy(result->data, styp_atom, sizeof(styp_atom)); // sidx if (earliest_pres_time > UINT_MAX) { p = dash_packager_write_sidx64_atom(p, stream_metadata, earliest_pres_time, moof_atom_size + mdat_atom_size); } else { p = dash_packager_write_sidx_atom(p, stream_metadata, (uint32_t)earliest_pres_time, moof_atom_size + mdat_atom_size); } // moof write_atom_header(p, moof_atom_size, 'm', 'o', 'o', 'f'); // moof.mfhd p = mp4_builder_write_mfhd_atom(p, segment_index); // moof.traf write_atom_header(p, traf_atom_size, 't', 'r', 'a', 'f'); // moof.traf.tfhd p = dash_packager_write_tfhd_atom(p, stream_metadata->media_info.track_id, sample_description_index); // moof.traf.tfdt if (earliest_pres_time > UINT_MAX) { p = dash_packager_write_tfdt64_atom(p, earliest_pres_time); } else { p = dash_packager_write_tfdt_atom(p, (uint32_t)earliest_pres_time); } // moof.traf.trun first_frame_offset = moof_atom_size + ATOM_HEADER_SIZE; if (mdat_prefix_writer != NULL) { first_frame_offset += mdat_prefix_writer->atom_size; } p = mp4_builder_write_trun_atom( p, stream_metadata->media_info.media_type, stream_metadata->frames, stream_metadata->frame_count, first_frame_offset); // moof.traf.xxx if (write_extra_traf_atoms_callback != NULL) { p = write_extra_traf_atoms_callback(write_extra_traf_atoms_context, p, moof_atom_size + ATOM_HEADER_SIZE); } // mdat write_atom_header(p, mdat_atom_size, 'm', 'd', 'a', 't'); // mdat prefix if (mdat_prefix_writer != NULL) { p = mdat_prefix_writer->write(mdat_prefix_writer->context, p); } result->len = p - result->data; if (result->len != result_size) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "dash_packager_build_fragment_header: result length %uz exceeded allocated length %uz", result->len, result_size); return VOD_UNEXPECTED; } return VOD_OK; }