Beispiel #1
0
static u_char*
dash_packager_init_mp4_write(
	u_char* p,
	request_context_t* request_context, 
	media_set_t* media_set, 
	init_mp4_sizes_t* sizes,
	atom_writer_t* extra_moov_atoms_writer,
	atom_writer_t* stsd_atom_writer)
{
	media_track_t* first_track = media_set->sequences[0].filtered_clips[0].first_track;

	// ftyp
	p = vod_copy(p, ftyp_atom, sizeof(ftyp_atom));

	// moov
	write_atom_header(p, sizes->moov_atom_size, 'm', 'o', 'o', 'v');

	// moov.mvhd
	if (media_set->sequences[0].filtered_clips[0].mvhd_atom.ptr != NULL)
	{
		// TODO: adjust the mvhd duration (can change in case of clipping or sequencing)
		p = vod_copy_atom(p, media_set->sequences[0].filtered_clips[0].mvhd_atom);
	}
	else if (media_set->total_duration > UINT_MAX)
	{
		p = dash_packager_write_mvhd64_atom(p, 1000, media_set->total_duration);
	}
	else
	{
		p = dash_packager_write_mvhd_atom(p, 1000, media_set->total_duration);
	}

	// moov.mvex
	write_atom_header(p, sizes->mvex_atom_size, 'm', 'v', 'e', 'x');

	// moov.mvex.trex
	p = dash_packager_write_trex_atom(p, first_track->media_info.track_id);

	// moov.trak
	write_atom_header(p, sizes->track_sizes.track_trak_size, 't', 'r', 'a', 'k');
	p = vod_copy_atom(p, first_track->raw_atoms[RTA_TKHD]);

	// moov.trak.mdia
	write_atom_header(p, sizes->track_sizes.track_mdia_size, 'm', 'd', 'i', 'a');
	p = vod_copy_atom(p, first_track->raw_atoms[RTA_MDHD]);
	p = vod_copy_atom(p, first_track->raw_atoms[RTA_HDLR]);

	// moov.trak.minf
	write_atom_header(p, sizes->track_sizes.track_minf_size, 'm', 'i', 'n', 'f');
	switch (first_track->media_info.media_type)
	{
	case MEDIA_TYPE_VIDEO:
		p = vod_copy(p, vmhd_atom, sizeof(vmhd_atom));
		break;
	case MEDIA_TYPE_AUDIO:
		p = vod_copy(p, smhd_atom, sizeof(smhd_atom));
		break;
	}
	p = vod_copy_atom(p, first_track->raw_atoms[RTA_DINF]);

	// moov.trak.minf.stbl
	write_atom_header(p, sizes->track_sizes.track_stbl_size, 's', 't', 'b', 'l');
	if (stsd_atom_writer != NULL)
	{
		p = stsd_atom_writer->write(stsd_atom_writer->context, p);
	}
	else
	{
		p = vod_copy_atom(p, first_track->raw_atoms[RTA_STSD]);
	}
	p = vod_copy(p, fixed_stbl_atoms, sizeof(fixed_stbl_atoms));

	// moov.xxx
	if (extra_moov_atoms_writer != NULL)
	{
		p = extra_moov_atoms_writer->write(extra_moov_atoms_writer->context, p);
	}

	return p;
}
vod_status_t
dash_packager_build_init_mp4(
	request_context_t* request_context, 
	mpeg_metadata_t* mpeg_metadata, 
	bool_t size_only,
	atom_writer_t* extra_moov_atoms_writer,
	atom_writer_t* stsd_atom_writer,
	vod_str_t* result)
{
	track_sizes_t track_sizes;
	size_t moov_atom_size;
	size_t mvex_atom_size;
	size_t result_size;
	size_t stsd_size;
	u_char* p;

	// calc moov atom size
	if (stsd_atom_writer != NULL)
	{
		stsd_size = stsd_atom_writer->atom_size;
	}
	else
	{
		stsd_size = mpeg_metadata->first_stream->raw_atoms[RTA_STSD].size;
	}

	dash_packager_get_track_sizes(mpeg_metadata->first_stream, stsd_size, &track_sizes);

	mvex_atom_size = ATOM_HEADER_SIZE + ATOM_HEADER_SIZE + sizeof(trex_atom_t);

	moov_atom_size = ATOM_HEADER_SIZE +
		mpeg_metadata->mvhd_atom.size +
		track_sizes.track_trak_size +
		mvex_atom_size;

	if (extra_moov_atoms_writer != NULL)
	{
		moov_atom_size += extra_moov_atoms_writer->atom_size;
	}

	result_size = sizeof(ftyp_atom) + moov_atom_size;

	// head request optimization
	if (size_only)
	{
		result->len = result_size;
		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_init_mp4: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	// ftyp
	p = vod_copy(result->data, ftyp_atom, sizeof(ftyp_atom));

	// moov
	write_atom_header(p, moov_atom_size, 'm', 'o', 'o', 'v');

	// moov.mvhd
	p = vod_copy_atom(p, mpeg_metadata->mvhd_atom);

	// moov.mvex
	write_atom_header(p, mvex_atom_size, 'm', 'v', 'e', 'x');

	// moov.mvex.trex
	p = dash_packager_write_trex_atom(p, mpeg_metadata->first_stream->media_info.track_id);

	// moov.trak
	write_atom_header(p, track_sizes.track_trak_size, 't', 'r', 'a', 'k');
	p = vod_copy_atom(p, mpeg_metadata->first_stream->raw_atoms[RTA_TKHD]);

	// moov.trak.mdia
	write_atom_header(p, track_sizes.track_mdia_size, 'm', 'd', 'i', 'a');
	p = vod_copy_atom(p, mpeg_metadata->first_stream->raw_atoms[RTA_MDHD]);
	p = vod_copy_atom(p, mpeg_metadata->first_stream->raw_atoms[RTA_HDLR]);

	// moov.trak.minf
	write_atom_header(p, track_sizes.track_minf_size, 'm', 'i', 'n', 'f');
	switch (mpeg_metadata->first_stream->media_info.media_type)
	{
	case MEDIA_TYPE_VIDEO:
		p = vod_copy(p, vmhd_atom, sizeof(vmhd_atom));
		break;
	case MEDIA_TYPE_AUDIO:
		p = vod_copy(p, smhd_atom, sizeof(smhd_atom));
		break;
	}
	p = vod_copy_atom(p, mpeg_metadata->first_stream->raw_atoms[RTA_DINF]);

	// moov.trak.minf.stbl
	write_atom_header(p, track_sizes.track_stbl_size, 's', 't', 'b', 'l');
	if (stsd_atom_writer != NULL)
	{
		p = stsd_atom_writer->write(stsd_atom_writer->context, p);
	}
	else
	{
		p = vod_copy_atom(p, mpeg_metadata->first_stream->raw_atoms[RTA_STSD]);
	}
	p = vod_copy(p, fixed_stbl_atoms, sizeof(fixed_stbl_atoms));

	// moov.xxx
	if (extra_moov_atoms_writer != NULL)
	{
		p = extra_moov_atoms_writer->write(extra_moov_atoms_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_init_mp4: result length %uz different than allocated length %uz",
			result->len, result_size);
		return VOD_UNEXPECTED;
	}

	return VOD_OK;
}