Beispiel #1
0
void quicktime_finalize_hdrl(quicktime_t *file, quicktime_hdrl_t *hdrl)
{
	int i;
	int64_t position = quicktime_position(file);
	int64_t total_frames = 0;
	double frame_rate = 0;

	for(i = 0; i < file->moov.total_tracks; i++)
	{
		quicktime_trak_t *trak = file->moov.trak[i];
		quicktime_strl_t *strl = hdrl->strl[i];

		if(trak->mdia.minf.is_video)
		{
			int length;
			quicktime_set_position(file, strl->length_offset);
			total_frames = length = quicktime_track_samples(file, trak);
			quicktime_write_int32_le(file, length);
			frame_rate = (double)trak->mdia.mdhd.time_scale /
				trak->mdia.minf.stbl.stts.table[0].sample_duration;
		}
		else
		if(trak->mdia.minf.is_audio)
		{
			int length, samples_per_chunk, wav_id, sample_size, sample_rate;
			quicktime_set_position(file, strl->length_offset);
			length = quicktime_track_samples(file, trak);
			quicktime_write_int32_le(file, length);

// dwScale and dwRate as per MSDN - // http://msdn.microsoft.com/library/default.asp?
//   url=/library/en-us/wcemultimedia5/html/wce50conAVIStreamHeaders.asp
			quicktime_set_position(file, strl->samples_per_chunk_offset);
			wav_id = ((quicktime_codec_t*)(file->atracks[0].codec))->wav_id;
			samples_per_chunk = wav_id == 1 ? 1 :
				quicktime_avg_chunk_samples(file, trak);
			quicktime_write_int32_le(file, samples_per_chunk);
			sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
			quicktime_write_int32_le(file, sample_rate);
			quicktime_set_position(file, strl->sample_size_offset);

// dwSampleSize as per MSDN
// as per http://www.virtualdub.org/blog/pivot/entry.php?id=27, many programs ignore this value
// sample_size in quicktime is in bits... so we must divide by 8
// FIXME: This has to be zero for _all_ VBR encodings, and other values are used for specific encodings
			sample_size = trak->mdia.minf.stbl.stsd.table[0].sample_size;
			quicktime_write_int32_le(file, wav_id != 1 ? sample_size :
				trak->mdia.minf.stbl.stsd.table[0].channels * sample_size / 8);
		}
	}

	if(total_frames)
	{
		quicktime_set_position(file, hdrl->bitrate_offset);
		quicktime_write_int32_le(file,
			file->total_length / (total_frames / frame_rate));
		quicktime_set_position(file, hdrl->frames_offset);
		quicktime_write_int32_le(file, total_frames);
	}

	quicktime_set_position(file, position);
}
Beispiel #2
0
int quicktime_make_streamable(char *in_path, char *out_path)
{
	quicktime_t file, *old_file, new_file;
	int moov_exists = 0, mdat_exists = 0, result, atoms = 1;
	int64_t mdat_start, mdat_size;
	quicktime_atom_t leaf_atom;
	int64_t moov_start, moov_end;
	int ftyp_exists = 0;
	int ftyp_size = 0;
	unsigned char *ftyp_data = 0;

	quicktime_init(&file);

/* find the moov atom in the old file */

	if(!(file.stream = fopen(in_path, "rb")))
	{
		perror("quicktime_make_streamable");
		return 1;
	}

	file.total_length = quicktime_get_file_length(in_path);

/* get the locations of moov and mdat atoms */
	do
	{
		result = quicktime_atom_read_header(&file, &leaf_atom);
//printf("0x%llx %s\n", quicktime_position(&file), leaf_atom.type);

		if(!result)
		{
			if(quicktime_atom_is(&leaf_atom, "ftyp"))
			{
				ftyp_exists = 1;
				ftyp_data = calloc(1, leaf_atom.size);
				ftyp_size = leaf_atom.size;
				quicktime_set_position(&file,
					quicktime_position(&file) - HEADER_LENGTH);
				quicktime_read_data(&file, (char*)ftyp_data, ftyp_size);
			}
			else
			if(quicktime_atom_is(&leaf_atom, "moov"))
			{
				moov_exists = atoms;
			}
			else
			if(quicktime_atom_is(&leaf_atom, "mdat"))
			{
				mdat_start = quicktime_position(&file) - HEADER_LENGTH;
				mdat_size = leaf_atom.size;
				mdat_exists = atoms;
			}

			quicktime_atom_skip(&file, &leaf_atom);

			atoms++;
		}
	}while(!result && quicktime_position(&file) < file.total_length);

	fclose(file.stream);

	if(!moov_exists)
	{
		printf("quicktime_make_streamable: no moov atom\n");
		if(ftyp_data) free(ftyp_data);
		return 1;
	}

	if(!mdat_exists)
	{
		printf("quicktime_make_streamable: no mdat atom\n");
		if(ftyp_data) free(ftyp_data);
		return 1;
	}

/* copy the old file to the new file */
	if(moov_exists && mdat_exists)
	{
/* moov wasn't the first atom */
		if(moov_exists > 1)
		{
			char *buffer;
			int64_t buf_size = 1000000;

			result = 0;

/* read the header proper */
			if(!(old_file = quicktime_open(in_path, 1, 0)))
			{
				if(ftyp_data) free(ftyp_data);
				return 1;
			}


/* open the output file */
			if(!(new_file.stream = fopen(out_path, "wb")))
			{
				perror("quicktime_make_streamable");
				result =  1;
			}
			else
			{
/* set up some flags */
				new_file.wr = 1;
				new_file.rd = 0;

/* Write ftyp header */
				if(ftyp_exists)
				{
					quicktime_write_data(&new_file, (char*)ftyp_data, ftyp_size);
				}


/* Write moov once to get final size with our substituted headers */
				moov_start = quicktime_position(&new_file);
				quicktime_write_moov(&new_file, &(old_file->moov), 0);
				moov_end = quicktime_position(&new_file);

printf("make_streamable 0x%llx 0x%llx\n", (long long)moov_end - moov_start, (long long)mdat_start);
				quicktime_shift_offsets(&(old_file->moov),
					moov_end - moov_start - mdat_start + ftyp_size);

/* Write again with shifted offsets */
				quicktime_set_position(&new_file, moov_start);
				quicktime_write_moov(&new_file, &(old_file->moov), 0);
				quicktime_set_position(old_file, mdat_start);

				if(!(buffer = calloc(1, buf_size)))
				{
					result = 1;
					printf("quicktime_make_streamable: out of memory\n");
				}
				else
				{
					while(quicktime_position(old_file) < mdat_start + mdat_size && !result)
					{
						if(quicktime_position(old_file) + buf_size > mdat_start + mdat_size)
							buf_size = mdat_start + mdat_size - quicktime_position(old_file);

						if(!quicktime_read_data(old_file, buffer, buf_size)) result = 1;
						if(!result)
						{
							if(!quicktime_write_data(&new_file, buffer, buf_size)) result = 1;
						}
					}
					free(buffer);
				}
				fclose(new_file.stream);
			}
			quicktime_close(old_file);
		}
		else
		{
			printf("quicktime_make_streamable: header already at 0 offset\n");
			if(ftyp_data) free(ftyp_data);
			return 0;
		}
	}

	if(ftyp_data) free(ftyp_data);
	return 0;
}
Beispiel #3
0
void quicktime_finalize_odml(quicktime_t *file, quicktime_hdrl_t *hdrl)
{
// Get length in frames
	quicktime_set_position(file, hdrl->total_frames_offset);
//	quicktime_write_int32_le(file, );
}
Beispiel #4
0
int quicktime_seek_start(quicktime_t *file)
{
	quicktime_set_position(file, file->mdat.atom.start + HEADER_LENGTH * 2);
	quicktime_update_positions(file);
	return 0;
}
Beispiel #5
0
int quicktime_check_sig(char *path)
{
	quicktime_t file;
	quicktime_atom_t leaf_atom;
	int result = 0, result1 = 0, result2 = 0;
	char avi_test[12];

	quicktime_init(&file);
	result = quicktime_file_open(&file, path, 1, 0);

	if(!result)
	{
// Check for Microsoft AVI
		quicktime_read_data(&file, avi_test, 12);
		quicktime_set_position(&file, 0);
		if(quicktime_match_32(avi_test, "RIFF") &&
			quicktime_match_32(avi_test + 8, "AVI "))
		{
			result2 = 1;
		}



/*
 * 		if(!result2)
 * // Check for Microsoft ASF
 * 		{
 * 			quicktime_guid_t guid;
 * 			quicktime_read_guid(&file, &guid);
 * 			quicktime_set_position(&file, 0);
 * 			if(!memcmp(&guid, &asf_header, sizeof(guid)))
 * 			{
 * 				printf("quicktime_check_sig: Got ASF\n");
 * 				result2 = 1;
 * 			}
 * 		}
 */

		if(!result2)
		{
			do
			{
				result1 = quicktime_atom_read_header(&file, &leaf_atom);

				if(!result1)
				{
/* just want the "moov" atom */
					if(quicktime_atom_is(&leaf_atom, "moov"))
					{
						result2 = 1;
					}
					else
						quicktime_atom_skip(&file, &leaf_atom);
				}
			}while(!result1 && !result2 && quicktime_position(&file) < file.total_length);
		}
	}

//printf(__FUNCTION__ " 2 %d\n", result2);
	quicktime_file_close(&file);
	quicktime_delete(&file);
	return result2;
}
Beispiel #6
0
int quicktime_read_info(quicktime_t *file)
{
	int result = 0, got_header = 0;
	int64_t start_position = quicktime_position(file);
	quicktime_atom_t leaf_atom;
	quicktime_guid_t guid;
	char avi_avi[4];
	int got_avi = 0;
	int got_asf = 0;
	file->use_avi = 0;
	file->use_asf = 0;

	quicktime_set_position(file, 0LL);

/* Test for ASF */
	quicktime_read_guid(file, &guid);
	quicktime_set_position(file, 0LL);
	if(!memcmp(&guid, &asf_header, sizeof(guid)))
	{
		printf("quicktime_read_info: Got ASF\n");
		got_asf = 1;
		got_header = 1;
	}

/* Test file format */
	if(!got_asf)
	{
		quicktime_set_position(file, 0LL);
		do
		{
			file->use_avi = 1;
			result = quicktime_atom_read_header(file, &leaf_atom);

			if(!result && quicktime_atom_is(&leaf_atom, "RIFF"))
			{
				quicktime_read_data(file, avi_avi, 4);
				if(quicktime_match_32(avi_avi, "AVI "))
				{
					got_avi = 1;
				}
				else
				{
					file->use_avi = 0;
					result = 0;
					break;
				}
			}
			else
			{
				file->use_avi = 0;
				result = 0;
				break;
			}
		}while(1);
	}

	if(got_avi) file->use_avi = 1;
	else
	if(got_asf) file->use_asf = 1;

	quicktime_set_position(file, 0LL);


/* McRoweSoft AVI section */
	if(file->use_avi)
	{
/* Import first RIFF */
		do
		{
			result = quicktime_atom_read_header(file, &leaf_atom);
			if(!result)
			{
				if(quicktime_atom_is(&leaf_atom, "RIFF"))
				{
					quicktime_read_riff(file, &leaf_atom);
/* Return success */
					got_header = 1;
				}
			}
		}while(!result &&
			!got_header &&
			quicktime_position(file) < file->total_length);

/* Construct indexes. */
		quicktime_import_avi(file);
	}
/* Quicktime section */
	else
	if(file->use_asf)
	{
		result = quicktime_read_asf(file);
		if(result) got_header = 0;
		else
		quicktime_dump_asf(file->asf);
	}
	else
	if(!file->use_avi)
	{
		do
		{
			result = quicktime_atom_read_header(file, &leaf_atom);

			if(!result)
			{
				if(quicktime_atom_is(&leaf_atom, "mdat"))
				{
					quicktime_read_mdat(file, &(file->mdat), &leaf_atom);
				}
				else
				if(quicktime_atom_is(&leaf_atom, "moov"))
				{
/* Set preload and preload the moov atom here */
					int64_t start_position = quicktime_position(file);
					long temp_size = leaf_atom.end - start_position;
					char *temp = malloc(temp_size);
					quicktime_set_preload(file,
						(temp_size < 0x100000) ? 0x100000 : temp_size);
					quicktime_read_data(file, temp, temp_size);
					quicktime_set_position(file, start_position);
					free(temp);

					if(quicktime_read_moov(file, &(file->moov), &leaf_atom))
						return 1;
					got_header = 1;
				}
				else
					quicktime_atom_skip(file, &leaf_atom);
			}
		}while(!result && quicktime_position(file) < file->total_length);










/* go back to the original position */
		quicktime_set_position(file, start_position);

	}

/* Initialize track map objects */
	if(got_header)
	{
		quicktime_init_maps(file);
	}

/* Shut down preload in case of an obsurdly high temp_size */
	quicktime_set_preload(file, 0);

	return !got_header;
}
Beispiel #7
0
void quicktime_read_stsd_video(quicktime_t *file, 
	quicktime_stsd_table_t *table, 
	quicktime_atom_t *parent_atom)
{
	quicktime_atom_t leaf_atom;
	int len;
	
	table->version = quicktime_read_int16(file);
	table->revision = quicktime_read_int16(file);
	quicktime_read_data(file, table->vendor, 4);
	table->temporal_quality = quicktime_read_int32(file);
	table->spatial_quality = quicktime_read_int32(file);
	table->width = quicktime_read_int16(file);
	table->height = quicktime_read_int16(file);
	table->dpi_horizontal = quicktime_read_fixed32(file);
	table->dpi_vertical = quicktime_read_fixed32(file);
	table->data_size = quicktime_read_int32(file);
	table->frames_per_sample = quicktime_read_int16(file);
	len = quicktime_read_char(file);
	quicktime_read_data(file, table->compressor_name, 31);
	table->depth = quicktime_read_int16(file);
	table->ctab_id = quicktime_read_int16(file);


/* The data needed for SVQ3 codec and maybe some others ? */
	struct ImageDescription *id;
	int stsd_size,fourcc,c,d;
	stsd_size = parent_atom->end - parent_atom->start;
	table->extradata_size = stsd_size - 4;
	id = (struct ImageDescription *) malloc(table->extradata_size);     // we do not include size
	table->extradata = (char *) id;
	
	memcpy(id->cType, table->format, 4);         // Fourcc
	id->version = table->version;
	id->revisionLevel = table->revision;
	memcpy(id->vendor, table->vendor, 4);     // I think mplayer screws up on this one, it turns bytes around! :)
	id->temporalQuality = table->temporal_quality;
	id->spatialQuality = table->spatial_quality;
	id->width = table->width;
	id->height = table->height;
	id->hRes = table->dpi_horizontal;
	id->vRes = table->dpi_vertical;
	id->dataSize = table->data_size;
	id->frameCount = table->frames_per_sample;
	id->name[0] = len;
	memcpy(&(id->name[1]), table->compressor_name, 31);
	id->depth = table->depth;
	id->clutID = table->ctab_id;
	if (quicktime_position(file) < parent_atom->end)
	{
		int position = quicktime_position(file);     // remember position
		int datalen = parent_atom->end - position;
		quicktime_read_data(file, ((char*)&id->clutID)+2, datalen);
		quicktime_set_position(file, position);      // return to previous position so parsing can go on
	}
	

	while(quicktime_position(file) < parent_atom->end)
	{
		quicktime_atom_read_header(file, &leaf_atom);
/*
 * printf("quicktime_read_stsd_video 1 %llx %llx %llx %s\n", 
 * leaf_atom.start, leaf_atom.end, quicktime_position(file),
 * leaf_atom.type);
 */


		if(quicktime_atom_is(&leaf_atom, "esds"))
		{
			quicktime_read_esds(file, &leaf_atom, &table->esds);
		}
		else
		if(quicktime_atom_is(&leaf_atom, "avcC"))
		{
			quicktime_read_avcc(file, &leaf_atom, &table->avcc);
		}
		else
		if(quicktime_atom_is(&leaf_atom, "ctab"))
		{
			quicktime_read_ctab(file, &(table->ctab));
		}
		else
		if(quicktime_atom_is(&leaf_atom, "gama"))
		{
			table->gamma = quicktime_read_fixed32(file);
		}
		else
		if(quicktime_atom_is(&leaf_atom, "fiel"))
		{
			table->fields = quicktime_read_char(file);
			table->field_dominance = quicktime_read_char(file);
		}
		else
			quicktime_atom_skip(file, &leaf_atom);


/* 		if(quicktime_atom_is(&leaf_atom, "mjqt")) */
/* 		{ */
/* 			quicktime_read_mjqt(file, &(table->mjqt)); */
/* 		} */
/* 		else */
/* 		if(quicktime_atom_is(&leaf_atom, "mjht")) */
/* 		{ */
/* 			quicktime_read_mjht(file, &(table->mjht)); */
/* 		} */
/* 		else */
	}
//printf("quicktime_read_stsd_video 2\n");
}
Beispiel #8
0
int quicktime_read_asf(quicktime_t *file)
{
	quicktime_asf_t *asf = calloc(1, sizeof(quicktime_asf_t));
	int got_header = 0;
	int debug = 1;
	int i;

	file->asf = asf;
	quicktime_set_position(file, 16 + 14);
	
	while(1)
	{
		quicktime_guid_t guid;
		int64_t guid_size;
		int64_t guid_start = quicktime_position(file);

		bzero(&guid, sizeof(guid));
		quicktime_read_guid(file, &guid);
		guid_size = quicktime_read_int64_le(file);

		printf("quicktime_read_asf start=0x%llx size=0x%llx\n", guid_start, guid_size);

// Glitch
		if(guid_size < 24) return 1;
		
		
		if(!memcmp(&guid, &file_header, sizeof(guid)))
		{
			quicktime_guid_t leaf_guid;
			got_header = 1;
			quicktime_read_guid(file, &leaf_guid);
			asf->header.file_size = quicktime_read_int64_le(file);
			asf->header.create_time = quicktime_read_int64_le(file);
			asf->header.total_packets = quicktime_read_int64_le(file);
			asf->header.send_time = quicktime_read_int64_le(file);
			asf->header.play_time = quicktime_read_int64_le(file);
			asf->header.preroll = quicktime_read_int32_le(file);
			asf->header.ignore = quicktime_read_int32_le(file);
			asf->header.flags = quicktime_read_int32_le(file);
			asf->header.min_packet = quicktime_read_int32_le(file);
			asf->header.max_packet = quicktime_read_int32_le(file);
			asf->header.max_bitrate = quicktime_read_int32_le(file);
			asf->header.packet_size = asf->header.max_packet;
		}
		else
		if(!memcmp(&guid, &index_guid, sizeof(guid)))
		{
			quicktime_guid_t leaf_guid;
			int max;
			int count;
			int total_packets = 0;

// Leaf Guid
			quicktime_read_guid(file, &leaf_guid);
// indexed interval
			quicktime_read_int64_le(file);
// max
			max = quicktime_read_int32_le(file);
// count
			asf->index_size = quicktime_read_int32_le(file);
			asf->index = calloc(sizeof(quicktime_asfpacket_t), asf->index_size);

			for(i = 0; i < asf->index_size; i++)
			{
				asf->index[i].number = quicktime_read_int32_le(file);
				asf->index[i].count = quicktime_read_int16_le(file);
			}
		}
		else
		if(!memcmp(&guid, &stream_header, sizeof(guid)))
		{
			quicktime_asfstream_t *stream = 
				asf->streams[asf->total_streams++] = 
				new_asfstream();
			quicktime_guid_t leaf_guid;
			quicktime_read_guid(file, &leaf_guid);
			if(!memcmp(&leaf_guid, &audio_stream, sizeof(leaf_guid)))
				stream->is_audio = 1;
			else
			if(!memcmp(&leaf_guid, &video_stream, sizeof(leaf_guid)))
				stream->is_video = 1;
			else
			if(!memcmp(&leaf_guid, &ext_stream_embed_stream_header, sizeof(leaf_guid)))
				stream->is_ext_audio = 1;
			quicktime_read_guid(file, &leaf_guid);
			
			stream->total_size = quicktime_read_int64_le(file);
			stream->type_specific_size = quicktime_read_int32_le(file);
			quicktime_read_int32_le(file);
			stream->id = quicktime_read_int16_le(file) & 0x7f;
			quicktime_read_int32_le(file);
			if(stream->is_ext_audio)
			{
				quicktime_read_guid(file, &leaf_guid);
                if (!memcmp(&leaf_guid, &ext_stream_audio_stream, sizeof(leaf_guid)))
				{
                    stream->is_audio = 1;
					stream->is_ext_audio = 0;
                    quicktime_read_guid(file, &leaf_guid);
                    quicktime_read_int32_le(file);
                    quicktime_read_int32_le(file);
                    quicktime_read_int32_le(file);
                    quicktime_read_guid(file, &leaf_guid);
                    quicktime_read_int32_le(file);
                }
			}
			
			
			if(stream->is_audio)
			{
// Get WAV header
				stream->codec_tag = quicktime_read_int16_le(file);
				stream->channels = quicktime_read_int16_le(file);
				stream->samplerate = quicktime_read_int32_le(file);
				stream->bitrate = quicktime_read_int32_le(file);
				stream->block_align = quicktime_read_int16_le(file);
				if(stream->type_specific_size == 14)
					stream->bits_per_sample = 8;
				else
					stream->bits_per_sample = quicktime_read_int16_le(file);
				if(stream->type_specific_size > 16)
				{
					stream->extradata_size = quicktime_read_int16_le(file);
        			if (stream->extradata_size > 0) 
					{
            			if (stream->extradata_size > stream->type_specific_size - 18)
                			stream->extradata_size = stream->type_specific_size - 18;
            			stream->extradata = calloc(1, stream->extradata_size + 1024);
            			quicktime_read_data(file, stream->extradata, stream->extradata_size);
        			}
					else
            			stream->extradata_size = 0;
					
					if(stream->type_specific_size - stream->extradata_size - 18 > 0)
						quicktime_set_position(file,
							quicktime_position(file) + 
							stream->type_specific_size - 
							stream->extradata_size - 18);
				}

// Make fourcc from codec_tag and bits_per_sample
			}
			else
			if(stream->is_video)
			{
				int size1;
				int size2;
				quicktime_read_int32_le(file);
				quicktime_read_int32_le(file);
				quicktime_read_char(file);
				size1 = quicktime_read_int16_le(file);
				size2 = quicktime_read_int32_le(file);
				stream->width = quicktime_read_int32_le(file);
				stream->height = quicktime_read_int32_le(file);
				quicktime_read_int16_le(file);
				stream->bits_per_sample = quicktime_read_int16_le(file);
				stream->codec_tag = quicktime_read_int32_le(file);
				quicktime_set_position(file, quicktime_position(file) + 20);
				if(size1 > 40)
				{
					stream->extradata_size = size1 - 40;
					stream->extradata = calloc(1, stream->extradata_size + 1024);
					quicktime_read_data(file, stream->extradata, stream->extradata_size);
				}

// Make fourcc from codec_tag
				stream->fourcc[0] = (stream->codec_tag & 0xff);
				stream->fourcc[1] = (stream->codec_tag & 0xff00) >> 8;
				stream->fourcc[2] = (stream->codec_tag & 0xff0000) >> 16;
				stream->fourcc[3] = (stream->codec_tag & 0xff000000) >> 24;
			}
		}