int quicktime_write_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { long offset; int result; long bytes; /* Defeat 32 bit file size limit. */ if(quicktime_test_position(file)) return 1; /* write chunk for 1 track */ bytes = samples * quicktime_audio_bits(file, track) / 8 * file->atracks[track].channels; offset = quicktime_position(file); result = quicktime_write_data(file, audio_buffer, bytes); if(result) result = 0; else result = 1; /* defeat fwrite's return */ quicktime_update_tables(file, file->atracks[track].track, offset, file->atracks[track].current_chunk, file->atracks[track].current_position, samples, 0, 0, 0, 0); file->atracks[track].current_position += samples; file->atracks[track].current_chunk++; return result; }
int quicktime_write_video_frame(quicktime_t *file, unsigned char *video_buffer, long bytes, int track, u_char isKeyFrame, long duration, long renderingOffset) { long offset = quicktime_position(file); int result = 0; /* Defeat 32 bit file size limit. */ if(quicktime_test_position(file)) return 1; result = quicktime_write_data(file, video_buffer, bytes); if(result) result = 0; else result = 1; quicktime_update_tables(file, file->vtracks[track].track, offset, file->vtracks[track].current_chunk, file->vtracks[track].current_position, 1, bytes, duration, isKeyFrame, renderingOffset); file->vtracks[track].current_position += 1; file->vtracks[track].current_chunk++; return result; }
int quicktime_write_audio_frame(quicktime_t *file, unsigned char *audio_buffer, long bytes, int track) { long offset = quicktime_position(file); int result = 0; /* Defeat 32 bit file size limit. */ if(quicktime_test_position(file)) return 1; result = quicktime_write_data(file, audio_buffer, bytes); if(result) result = 0; else result = 1; quicktime_update_tables(file, file->atracks[track].track, offset, file->atracks[track].current_chunk, file->atracks[track].current_position, 1, bytes, 0, 0, 0); file->atracks[track].current_position += 1; file->atracks[track].current_chunk++; return result; }
quicktime_t* quicktime_open(char *filename, int rd, int wr) { quicktime_t *new_file = calloc(1, sizeof(quicktime_t)); int result = 0; //printf("quicktime_open 1\n"); quicktime_init(new_file); new_file->wr = wr; new_file->rd = rd; new_file->mdat.atom.start = 0; result = quicktime_file_open(new_file, filename, rd, wr); if(!result) { if(rd) { if(quicktime_read_info(new_file)) { quicktime_close(new_file); fprintf(stderr, "quicktime_open: error in header\n"); new_file = 0; } } /* start the data atom */ /* also don't want to do this if making a streamable file */ if(wr) { quicktime_set_presave(new_file, 1); // android requires the ftyp header const unsigned char ftyp_data[] = { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32, 0x00, 0x00, 0x00, 0x01, 0x6d, 0x70, 0x34, 0x32, 0x61, 0x76, 0x63, 0x31 }; quicktime_write_data(new_file, (char*)ftyp_data, sizeof(ftyp_data)); quicktime_atom_write_header64(new_file, &new_file->mdat.atom, "mdat"); quicktime_set_presave(new_file, 0); } } else { //printf("quicktime_open 10\n"); quicktime_close(new_file); //printf("quicktime_open 100\n"); new_file = 0; } return new_file; }
int quicktime_write_hdlr(quicktime_t *file, quicktime_hdlr_t *hdlr) { quicktime_atom_t atom; quicktime_atom_write_header(file, &atom, "hdlr"); quicktime_write_char(file, hdlr->version); quicktime_write_int24(file, hdlr->flags); if (file->use_mp4) { int i; quicktime_write_int32(file, 0x00000000); quicktime_write_char32(file, hdlr->component_subtype); for (i = 0; i < 3; i++) { quicktime_write_int32(file, 0x00000000); } quicktime_write_data(file, hdlr->component_name, strlen(hdlr->component_name) + 1); } else { quicktime_write_char32(file, hdlr->component_type); quicktime_write_char32(file, hdlr->component_subtype); quicktime_write_int32(file, hdlr->component_manufacturer); quicktime_write_int32(file, hdlr->component_flags); quicktime_write_int32(file, hdlr->component_flag_mask); quicktime_write_pascal(file, hdlr->component_name); } quicktime_atom_write_footer(file, &atom); }
int quicktime_write_audio(quicktime_t *file, char *audio_buffer, long samples, int track) { int result; int64_t bytes; quicktime_atom_t chunk_atom; quicktime_audio_map_t *track_map = &file->atracks[track]; quicktime_trak_t *trak = track_map->track; /* write chunk for 1 track */ bytes = samples * quicktime_audio_bits(file, track) / 8 * file->atracks[track].channels; quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, audio_buffer, bytes); quicktime_write_chunk_footer(file, trak, track_map->current_chunk, &chunk_atom, samples); /* file->atracks[track].current_position += samples; */ file->atracks[track].current_chunk++; return result; }
static int encode(quicktime_t *file, unsigned char **row_pointers, int track) { int bytes; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_trak_t *trak = vtrack->track; quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int result = 1; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; quicktime_atom_t chunk_atom; initialize(vtrack, codec, width, height); bytes = height * codec->bytes_per_line; cmodel_transfer(codec->rows, row_pointers, 0, 0, 0, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, width, height, 0, 0, width, height, file->color_model, BC_YUV422, 0, width, codec->coded_w); if( codec->is_2vuy ) convert_encode_2vuy(codec); else convert_encode_yuv2(codec); quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, (char*)codec->work_buffer, bytes); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); vtrack->current_chunk++; return result; }
int quicktime_write_int16_le(quicktime_t *file, int number) { unsigned char data[2]; data[1] = (number & 0xff00) >> 8; data[0] = (number & 0xff); return quicktime_write_data(file, data, 2); }
void quicktime_write_avcc(quicktime_t *file, quicktime_avcc_t *avcc) { quicktime_atom_t atom; quicktime_atom_write_header(file, &atom, "avcC"); quicktime_write_data(file, avcc->data, avcc->data_size); quicktime_atom_write_footer(file, &atom); }
static int encode(quicktime_t *file, unsigned char **row_pointers, int track) { int64_t offset = quicktime_position(file); quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_v308_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; quicktime_trak_t *trak = vtrack->track; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; int bytes = width * height * 3; int result = 0; unsigned char **output_rows; int i; quicktime_atom_t chunk_atom; if(!codec->work_buffer) codec->work_buffer = malloc(vtrack->track->tkhd.track_width * vtrack->track->tkhd.track_height * 3); output_rows = malloc(sizeof(unsigned char*) * height); for(i = 0; i < height; i++) output_rows[i] = codec->work_buffer + i * width * 3; cmodel_transfer(output_rows, row_pointers, 0, 0, 0, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, width, height, 0, 0, width, height, file->color_model, BC_VYU888, 0, width, width); quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, codec->work_buffer, bytes); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); vtrack->current_chunk++; free(output_rows); return result; }
void quicktime_write_stsd_video(quicktime_t *file, quicktime_stsd_table_t *table) { quicktime_write_int16(file, table->version); quicktime_write_int16(file, table->revision); quicktime_write_data(file, table->vendor, 4); quicktime_write_int32(file, table->temporal_quality); quicktime_write_int32(file, table->spatial_quality); quicktime_write_int16(file, table->width); quicktime_write_int16(file, table->height); quicktime_write_fixed32(file, table->dpi_horizontal); quicktime_write_fixed32(file, table->dpi_vertical); quicktime_write_int32(file, table->data_size); quicktime_write_int16(file, table->frames_per_sample); quicktime_write_char(file, strlen(table->compressor_name)); quicktime_write_data(file, table->compressor_name, 31); quicktime_write_int16(file, table->depth); quicktime_write_int16(file, table->ctab_id); // Write field order for mjpa if(table->fields) { quicktime_atom_t atom; quicktime_atom_write_header(file, &atom, "fiel"); quicktime_write_char(file, table->fields); quicktime_write_char(file, table->field_dominance); quicktime_atom_write_footer(file, &atom); } // Write header for mp4v if(table->esds.mpeg4_header_size && table->esds.mpeg4_header) { quicktime_write_esds(file, &table->esds, 1, 0); } if(table->avcc.data_size) { quicktime_write_avcc(file, &table->avcc); } // Write another 32 bits if(table->version == 1) quicktime_write_int32(file, 0x0); }
int quicktime_write_int24(quicktime_t *file, long number) { unsigned char data[3]; data[0] = (number & 0xff0000) >> 16; data[1] = (number & 0xff00) >> 8; data[2] = (number & 0xff); return quicktime_write_data(file, data, 3); }
void quicktime_write_dref_table(quicktime_t *file, quicktime_dref_table_t *table) { int len = strlen(table->data_reference); quicktime_write_int32(file, 12 + len); quicktime_write_char32(file, table->type); quicktime_write_char(file, table->version); quicktime_write_int24(file, table->flags); if(len) quicktime_write_data(file, table->data_reference, len); }
int quicktime_write_int32_le(quicktime_t *file, long value) { unsigned char data[4]; data[3] = (value & 0xff000000) >> 24; data[2] = (value & 0xff0000) >> 16; data[1] = (value & 0xff00) >> 8; data[0] = value & 0xff; return quicktime_write_data(file, data, 4); }
void quicktime_write_stsd_audio(quicktime_t *file, quicktime_stsd_table_t *table) { quicktime_write_int16(file, table->version); quicktime_write_int16(file, table->revision); quicktime_write_data(file, table->vendor, 4); quicktime_write_int16(file, table->channels); quicktime_write_int16(file, table->sample_size); quicktime_write_int16(file, table->compression_id); quicktime_write_int16(file, table->packet_size); quicktime_write_fixed32(file, table->sample_rate); // Write header for mp4a if(table->esds.mpeg4_header_size && table->esds.mpeg4_header) { // Android requires leaving out the WAVE header #if 0 // Version 1 info quicktime_write_int32(file, 0); quicktime_write_int32(file, 0); quicktime_write_int32(file, 0); quicktime_write_int32(file, 0); quicktime_atom_t wave_atom; quicktime_atom_t frma_atom; quicktime_atom_t mp4a_atom; quicktime_atom_write_header(file, &wave_atom, "wave"); quicktime_atom_write_header(file, &frma_atom, "frma"); quicktime_write_data(file, "mp4a", 4); quicktime_atom_write_footer(file, &frma_atom); quicktime_atom_write_header(file, &mp4a_atom, "mp4a"); quicktime_write_int32(file, 0x0); quicktime_atom_write_footer(file, &mp4a_atom); #endif // 0 quicktime_write_esds(file, &table->esds, 0, 1); // quicktime_atom_write_footer(file, &wave_atom); } }
int quicktime_write_tkhd(quicktime_t *file, quicktime_tkhd_t *tkhd) { quicktime_atom_t atom; quicktime_atom_write_header(file, &atom, "tkhd"); quicktime_write_char(file, tkhd->version); quicktime_write_int24(file, tkhd->flags); quicktime_write_int32(file, tkhd->creation_time); quicktime_write_int32(file, tkhd->modification_time); quicktime_write_int32(file, tkhd->track_id); quicktime_write_int32(file, tkhd->reserved1); quicktime_write_int32(file, tkhd->duration); if (file->use_mp4) { int i; for (i = 0; i < 3; i++) { quicktime_write_int32(file, 0x00000000); } if (tkhd->is_audio) { quicktime_write_int16(file, 0x0100); } else { quicktime_write_int16(file, 0x0000); } quicktime_write_int16(file, 0x0000); quicktime_write_int32(file, 0x00010000); for (i = 0; i < 3; i++) { quicktime_write_int32(file, 0x00000000); } quicktime_write_int32(file, 0x00010000); for (i = 0; i < 3; i++) { quicktime_write_int32(file, 0x00000000); } quicktime_write_int32(file, 0x40000000); if (tkhd->is_video) { quicktime_write_int32(file, 0x01400000); quicktime_write_int32(file, 0x00F00000); } else { quicktime_write_int32(file, 0x00000000); quicktime_write_int32(file, 0x00000000); } } else { quicktime_write_data(file, tkhd->reserved2, 8); quicktime_write_int16(file, tkhd->layer); quicktime_write_int16(file, tkhd->alternate_group); quicktime_write_fixed16(file, tkhd->volume); quicktime_write_int16(file, tkhd->reserved3); quicktime_write_matrix(file, &(tkhd->matrix)); quicktime_write_fixed32(file, tkhd->track_width); quicktime_write_fixed32(file, tkhd->track_height); } quicktime_atom_write_footer(file, &atom); }
int quicktime_write_fixed16(quicktime_t *file, float number) { unsigned char data[2]; int a, b; a = number; b = (number - a) * 256; data[0] = a; data[1] = b; return quicktime_write_data(file, data, 2); }
static int encode(quicktime_t *file, unsigned char **row_pointers, int track) { quicktime_video_map_t *vtrack = &(file->vtracks[track]); initialize(vtrack); quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; quicktime_trak_t *trak = vtrack->track; mjpeg_set_quality(codec->mjpeg, codec->quality); mjpeg_set_float(codec->mjpeg, codec->use_float); //int64_t offset = quicktime_position(file); int result = 0; long field2_offset; quicktime_atom_t chunk_atom; //printf("encode 1\n"); mjpeg_set_cpus(codec->mjpeg, file->cpus); mjpeg_compress(codec->mjpeg, row_pointers, row_pointers[0], row_pointers[1], row_pointers[2], file->color_model, file->cpus); if(codec->jpeg_type == JPEG_MJPA) { if(file->use_avi) { mjpeg_insert_avi_markers(&codec->mjpeg->output_data, &codec->mjpeg->output_size, &codec->mjpeg->output_allocated, 2, &field2_offset); } else { mjpeg_insert_quicktime_markers(&codec->mjpeg->output_data, &codec->mjpeg->output_size, &codec->mjpeg->output_allocated, 2, &field2_offset); } } quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, (char*)mjpeg_output_buffer(codec->mjpeg), mjpeg_output_size(codec->mjpeg)); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); vtrack->current_chunk++; //printf("encode 100\n"); return result; }
void quicktime_write_stsd_table(quicktime_t *file, quicktime_minf_t *minf, quicktime_stsd_table_t *table) { quicktime_atom_t atom; quicktime_atom_write_header(file, &atom, table->format); /*printf("quicktime_write_stsd_table %c%c%c%c\n", table->format[0], table->format[1], table->format[2], table->format[3]); */ quicktime_write_data(file, table->reserved, 6); quicktime_write_int16(file, table->data_reference); if(minf->is_audio) quicktime_write_stsd_audio(file, table); if(minf->is_video) quicktime_write_stsd_video(file, table); quicktime_atom_write_footer(file, &atom); }
int quicktime_write_esds_common(quicktime_t *file, quicktime_esds_t *esds, int esid, u_int objectType, u_int streamType) { quicktime_atom_t atom; if (!file->use_mp4) { return 0; } quicktime_atom_write_header(file, &atom, "esds"); quicktime_write_char(file, esds->version); quicktime_write_int24(file, esds->flags); quicktime_write_char(file, 0x03); /* ES_DescrTag */ quicktime_write_mp4_descr_length(file, 3 + (5 + (13 + (5 + esds->decoderConfigLen))) + 3, FALSE); quicktime_write_int16(file, esid); quicktime_write_char(file, 0x10); /* streamPriorty = 16 (0-31) */ /* DecoderConfigDescriptor */ quicktime_write_char(file, 0x04); /* DecoderConfigDescrTag */ quicktime_write_mp4_descr_length(file, 13 + (5 + esds->decoderConfigLen), FALSE); quicktime_write_char(file, objectType); /* objectTypeIndication */ quicktime_write_char(file, streamType); /* streamType */ quicktime_write_int24(file, 0); /* buffer size */ quicktime_write_int32(file, 0); /* max bitrate */ quicktime_write_int32(file, 0); /* average bitrate */ quicktime_write_char(file, 0x05); /* DecSpecificInfoTag */ quicktime_write_mp4_descr_length(file, esds->decoderConfigLen, FALSE); quicktime_write_data(file, esds->decoderConfig, esds->decoderConfigLen); /* SLConfigDescriptor */ quicktime_write_char(file, 0x06); /* SLConfigDescrTag */ quicktime_write_char(file, 0x01); /* length */ quicktime_write_char(file, 0x02); /* constant in mp4 files */ /* no IPI_DescrPointer */ /* no IP_IdentificationDataSet */ /* no IPMP_DescriptorPointer */ /* no LanguageDescriptor */ /* no QoS_Descriptor */ /* no RegistrationDescriptor */ /* no ExtensionDescriptor */ quicktime_atom_write_footer(file, &atom); }
static int quicktime_write_media_hint(quicktime_t* file, u_char* hintBuffer, long hintBufferSize, quicktime_trak_t* hintTrak, long* pSampleNumber, long hintSampleDuration, u_char isSyncSample) { long offset = quicktime_position(file); quicktime_hint_info_t hintInfo; int result = 0; /* handle 32 bit file size limit */ if (quicktime_test_position(file)) { return 1; } /* get info about this hint */ quicktime_get_hint_info(hintBuffer, hintBufferSize, &hintInfo); /* update overall info */ hintTrak->hint_udta.hinf.trpy.numBytes += hintInfo.trpy; hintTrak->hint_udta.hinf.nump.numPackets += hintInfo.nump; hintTrak->hint_udta.hinf.tpyl.numBytes += hintInfo.tpyl; hintTrak->hint_udta.hinf.dmed.numBytes += hintInfo.dmed; hintTrak->hint_udta.hinf.drep.numBytes += hintInfo.drep; hintTrak->hint_udta.hinf.dimm.numBytes += hintInfo.dimm; hintTrak->hint_udta.hinf.tmin.milliSecs = MAX(hintInfo.tmin, hintTrak->hint_udta.hinf.tmin.milliSecs); hintTrak->hint_udta.hinf.tmax.milliSecs = MAX(hintInfo.tmax, hintTrak->hint_udta.hinf.tmax.milliSecs); hintTrak->hint_udta.hinf.pmax.numBytes = MAX(hintInfo.pmax, hintTrak->hint_udta.hinf.pmax.numBytes); hintTrak->mdia.minf.hmhd.maxPDUsize = hintTrak->hint_udta.hinf.pmax.numBytes; hintTrak->mdia.minf.hmhd.avgPDUsize = hintTrak->hint_udta.hinf.trpy.numBytes / hintTrak->hint_udta.hinf.nump.numPackets; /* write the hint data */ result = quicktime_write_data(file, hintBuffer, hintBufferSize); result = (result ? 0 : 1); quicktime_update_tables(file, hintTrak, offset, *pSampleNumber + 1, *pSampleNumber, 1, hintBufferSize, hintSampleDuration, isSyncSample, 0); (*pSampleNumber)++; return result; }
int quicktime_write_fixed32(quicktime_t *file, float number) { unsigned char data[4]; int a, b; a = number; b = (number - a) * 65536; data[0] = a >> 8; data[1] = a & 0xff; data[2] = b >> 8; data[3] = b & 0xff; return quicktime_write_data(file, data, 4); }
int quicktime_write_int64_le(quicktime_t *file, int64_t value) { unsigned char data[8]; data[7] = (((uint64_t)value) & 0xff00000000000000LL) >> 56; data[6] = (((uint64_t)value) & 0xff000000000000LL) >> 48; data[5] = (((uint64_t)value) & 0xff0000000000LL) >> 40; data[4] = (((uint64_t)value) & 0xff00000000LL) >> 32; data[3] = (((uint64_t)value) & 0xff000000LL) >> 24; data[2] = (((uint64_t)value) & 0xff0000LL) >> 16; data[1] = (((uint64_t)value) & 0xff00LL) >> 8; data[0] = ((uint64_t)value) & 0xff; return quicktime_write_data(file, data, 8); }
void quicktime_write_tkhd(quicktime_t *file, quicktime_tkhd_t *tkhd) { quicktime_atom_t atom; quicktime_atom_write_header(file, &atom, "tkhd"); quicktime_write_char(file, tkhd->version); quicktime_write_int24(file, tkhd->flags); quicktime_write_int32(file, tkhd->creation_time); quicktime_write_int32(file, tkhd->modification_time); quicktime_write_int32(file, tkhd->track_id); quicktime_write_int32(file, tkhd->reserved1); quicktime_write_int32(file, tkhd->duration); quicktime_write_data(file, tkhd->reserved2, 8); quicktime_write_int16(file, tkhd->layer); quicktime_write_int16(file, tkhd->alternate_group); quicktime_write_fixed16(file, tkhd->volume); quicktime_write_int16(file, tkhd->reserved3); quicktime_write_matrix(file, &(tkhd->matrix)); quicktime_write_fixed32(file, tkhd->track_width); quicktime_write_fixed32(file, tkhd->track_height); quicktime_atom_write_footer(file, &atom); }
int quicktime_write_frame(quicktime_t *file, unsigned char *video_buffer, int64_t bytes, int track) { int64_t offset = quicktime_position(file); int result = 0; quicktime_atom_t chunk_atom; quicktime_video_map_t *vtrack = &file->vtracks[track]; quicktime_trak_t *trak = vtrack->track; quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, video_buffer, bytes); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); file->vtracks[track].current_position++; file->vtracks[track].current_chunk++; return result; }
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_length; 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 { /*printf("%x\n", quicktime_position(&file)); */ result = quicktime_atom_read_header(&file, &leaf_atom); if(!result) { if(quicktime_atom_is(&leaf_atom, "moov")) { moov_exists = atoms; moov_length = leaf_atom.size; } 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"); return 1; } if(!mdat_exists) { printf("quicktime_make_streamable: no mdat atom\n"); 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))) { return 1; } quicktime_shift_offsets(&(old_file->moov), moov_length); /* 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; quicktime_write_moov(&new_file, &(old_file->moov)); 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"); return 0; } } return 0; }
static int encode(quicktime_t *file, int16_t **input_i, float **input_f, int track, long samples) { int result = 0; int64_t i, j, step; int64_t chunk_bytes; int64_t overflow_start; int64_t chunk_samples; /* Samples in the current chunk to be written */ quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_ima4_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; quicktime_trak_t *trak = track_map->track; int16_t *input_ptr; unsigned char *output_ptr; quicktime_atom_t chunk_atom; /* Get buffer sizes */ if(codec->work_buffer && codec->work_size < (samples + codec->work_overflow + 1) * track_map->channels) { /* Create new buffer */ int64_t new_size = (samples + codec->work_overflow + 1) * track_map->channels; int16_t *new_buffer = malloc(sizeof(int16_t) * new_size); /* Copy overflow */ for(i = 0; i < codec->work_overflow * track_map->channels; i++) new_buffer[i] = codec->work_buffer[i]; /* Swap pointers. */ free(codec->work_buffer); codec->work_buffer = new_buffer; codec->work_size = new_size; } else if(!codec->work_buffer) { /* No buffer in the first place. */ codec->work_size = (samples + codec->work_overflow) * track_map->channels; /* Make the allocation enough for at least the flush routine. */ if(codec->work_size < SAMPLES_PER_BLOCK * track_map->channels) codec->work_size = SAMPLES_PER_BLOCK * track_map->channels; codec->work_buffer = malloc(sizeof(int16_t) * codec->work_size); } /* Get output size */ chunk_bytes = ima4_samples_to_bytes(samples + codec->work_overflow, track_map->channels); if(codec->read_buffer && codec->read_size < chunk_bytes) { free(codec->read_buffer); codec->read_buffer = 0; } if(!codec->read_buffer) { codec->read_buffer = malloc(chunk_bytes); codec->read_size = chunk_bytes; } if(!codec->last_samples) { codec->last_samples = malloc(sizeof(int) * track_map->channels); for(i = 0; i < track_map->channels; i++) { codec->last_samples[i] = 0; } } if(!codec->last_indexes) { codec->last_indexes = malloc(sizeof(int) * track_map->channels); for(i = 0; i < track_map->channels; i++) { codec->last_indexes[i] = 0; } } /* Arm the input buffer after the last overflow */ step = track_map->channels; for(j = 0; j < track_map->channels; j++) { input_ptr = codec->work_buffer + codec->work_overflow * track_map->channels + j; if(input_i) { for(i = 0; i < samples; i++) { *input_ptr = input_i[j][i]; input_ptr += step; } } else if(input_f) { for(i = 0; i < samples; i++) { *input_ptr = (int16_t)(input_f[j][i] * 32767); input_ptr += step; } } } /* Encode from the input buffer to the read_buffer up to a multiple of */ /* blocks. */ input_ptr = codec->work_buffer; output_ptr = codec->read_buffer; for(i = 0; i + SAMPLES_PER_BLOCK <= samples + codec->work_overflow; i += SAMPLES_PER_BLOCK) { for(j = 0; j < track_map->channels; j++) { ima4_encode_block(track_map, output_ptr, input_ptr + j, track_map->channels, j); output_ptr += BLOCK_SIZE; } input_ptr += SAMPLES_PER_BLOCK * track_map->channels; } /* Write to disk */ chunk_samples = (int64_t)((samples + codec->work_overflow) / SAMPLES_PER_BLOCK) * SAMPLES_PER_BLOCK; /*printf("quicktime_encode_ima4 1 %ld\n", chunk_samples); */ /* The block division may result in 0 samples getting encoded. */ /* Don't write 0 samples. */ if(chunk_samples) { quicktime_write_chunk_header(file, trak, &chunk_atom); result = quicktime_write_data(file, (char*)codec->read_buffer, chunk_bytes); quicktime_write_chunk_footer(file, trak, track_map->current_chunk, &chunk_atom, chunk_samples); if(result) result = 0; else result = 1; /* defeat fwrite's return */ track_map->current_chunk++; } /* Move the last overflow to the front */ overflow_start = i; input_ptr = codec->work_buffer; for(i = overflow_start * track_map->channels ; i < (samples + codec->work_overflow) * track_map->channels; i++) { *input_ptr++ = codec->work_buffer[i]; } codec->work_overflow = samples + codec->work_overflow - overflow_start; return result; }
void quicktime_write_pascal(quicktime_t *file, char *data) { char len = strlen(data); quicktime_write_data(file, &len, 1); quicktime_write_data(file, data, len); }
int quicktime_write_char(quicktime_t *file, char x) { return quicktime_write_data(file, &x, 1); }
int quicktime_write_char32(quicktime_t *file, char *string) { return quicktime_write_data(file, string, 4); }