Mercurial > hg > enc-imaf
view IM_AF Encoder/IM_AM Encoder/main.c @ 0:138a3cea9792
Different files related to my project, including the encoder (I made it) and decoder. Also I added the mp4atoms as an example.
MP4atoms belong to the IMAF player library.
author | Eugenio Oñate Hospital <eo301@eecs.qmul.ac.uk> |
---|---|
date | Wed, 04 Jul 2012 22:16:23 +0100 |
parents | |
children | 19490164927c |
line wrap: on
line source
// // main.c // IM_AM Enco§er // // Created by eugenio oñate hospital on 14/06/12. // Copyright (c) 2012 QM. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "IM_AF Encoder.h" #define maxtracks 10 /*Prototype*/ void filetypebx(FileTypeBox *ftyp); void mdatbox(MediaDataBox *mdat, int, namestrack *namet, FILE *imf); void moovheaderbox(MovieBox *moov, int, int); void trackstructure(MovieBox *moov, int, int, namestrack namet); void samplecontainer(MovieBox *moov, int); void groupscontainer(MovieBox *moov); void presetcontainer(MovieBox *moov); void metadata(MetaBox *meta); int getflags(); u32 getdurationtrack(); int getentrycount(); char setnametrack(); int getnextID(); int getelemID(); int main () { //variables FileTypeBox ftyp; MediaDataBox mdat; MovieBox moov; MetaBox meta; namestrack namet; FILE *imf; int numtrack,totaltracks=0, flags; // char typetrack[6]; /* Obtain current time as seconds elapsed since the Epoch. */ time_t clock = time(NULL); printf("Welcome to the IM_AF encoder\n"); printf("This program will allow you to create an IM_AF file.\n"); printf("How many tracks there will be in your IMAF file?\n"); scanf("%d",&totaltracks); fflush(stdin); //totaltracks = 1; while (totaltracks > maxtracks) { printf("Sorry, for this version the number maximum ot tracks is 10\n"); printf("How many tracks there will be in your IMAF file:\n"); scanf("%d",&totaltracks); } //Create the file imf = fopen ("/Users/eugin/Desktop/IM_AF Encoder/IM_AM Encoder/example1.ima","wb"); if (imf == NULL) { printf("Error opening input file\n"); system("pause"); exit(1); } //Define the File Type Box filetypebx(&ftyp); fwrite(&ftyp, sizeof(FileTypeBox),1, imf); //Movie Header - Overall declarations moovheaderbox(&moov, clock, numtrack); //For each track write track information for (numtrack = 0; numtrack < totaltracks; numtrack++) { //flags = getflags(); flags = 1; if (flags == 1){ // Track enable trackstructure(&moov, numtrack, clock, namet); } } //Groups groupscontainer(&moov); //Presets presetcontainer(&moov); //Write the information in FILE and close it fwrite(&moov, sizeof(MovieBox),1, imf); //Metadata metadata(&meta); fwrite(&meta, sizeof(MetaBox),1, imf); //Media Data Box - Contains the audio mdatbox(&mdat, totaltracks, &namet, imf); //Close File fclose(imf); //Testing the code....... imf = fopen ("/Users/eugin/Desktop/IM_AF Encoder/IM_AM Encoder/example1.ima","rb"); fread(&ftyp,sizeof(FileTypeBox),1,imf); fclose(imf); printf("minor version %d\n",ftyp.compatible_brands[0]); return 0; } void filetypebx(FileTypeBox *ftyp){ ftyp->major_brand = 'im01'; ftyp->minor_version = '0'; ftyp->compatible_brands[0] = 'im01'; ftyp->compatible_brands[1] = 'isom'; ftyp->compatible_brands[2] = 'im03'; ftyp->compatible_brands[3] = 'im12'; ftyp->compatible_brands[4] = 'im21'; } void mdatbox(MediaDataBox *mdat, int totaltracks, namestrack *namet, FILE *imf){ int exist, i, cnt, sz; FILE *song; char nametrack[20], pathdir[60] ="/Users/eugin/Desktop/IM_AF Encoder/"; for (i=0; i<totaltracks; i++) { strcpy(pathdir, "/Users/eugin/Desktop/IM_AF Encoder/"); printf("Name of the track number: %d\n", i+1); fflush(stdin); scanf("%s", nametrack); strcat(pathdir, nametrack); exist = 0; //Check if the track exist and then open it. while (exist == 0){ song = fopen(pathdir, "rb"); if((song)==NULL) { printf("Name does not exist. Try again:\n"); fflush(stdin); scanf("%s", nametrack); strcpy(pathdir, "/Users/eugin/Desktop/IM_AF Encoder/"); strcat(pathdir, nametrack); printf("%s\n",pathdir); }else{ exist = 1; } } strcpy (namet[i]->title, nametrack); fseek(song, 0L, SEEK_END); sz = ftell(song); printf("%d \n",sz); //Read track fseek (song, 0, SEEK_SET); for (cnt = 0; cnt < 200000; cnt++) { // printf("%d\n", cnt); fread(&mdat[i]->data, sizeof(u32),1,song); fwrite(&mdat, sizeof(MediaDataBox),1, imf); } fclose(song); } } void moovheaderbox (MovieBox *moov,int clock, int numtrack){ moov->MovieHeaderBox.creation_time = clock; moov->MovieHeaderBox.modification_time = clock; moov->MovieHeaderBox.timescale = 60; // moov->MovieHeaderBox.duration = getdurationtrack(); moov->MovieHeaderBox.duration = 10; moov->MovieHeaderBox.rate = 1; moov->MovieHeaderBox.volume = 1; moov->MovieHeaderBox.reserved=0; moov->MovieHeaderBox.reserved2[0] = 0; moov->MovieHeaderBox.reserved2[1] = 0; moov->MovieHeaderBox.matrix[0] = 0x00010000; moov->MovieHeaderBox.matrix[1] = 0; moov->MovieHeaderBox.matrix[2] = 0; moov->MovieHeaderBox.matrix[3] = 0; moov->MovieHeaderBox.matrix[4] = 0x00010000; moov->MovieHeaderBox.matrix[5] = 0; moov->MovieHeaderBox.matrix[6] = 0; moov->MovieHeaderBox.matrix[7] = 0; moov->MovieHeaderBox.matrix[8] = 0x40000000; moov->MovieHeaderBox.pre_defined[0] = 0; moov->MovieHeaderBox.pre_defined[1] = 0; moov->MovieHeaderBox.pre_defined[2] = 0; moov->MovieHeaderBox.pre_defined[3] = 0; moov->MovieHeaderBox.pre_defined[4] = 0; moov->MovieHeaderBox.pre_defined[5] = 0; // moov->MovieHeaderBox.next_track_ID = getnextID(); moov->MovieHeaderBox.next_track_ID = numtrack + 2; } void trackstructure (MovieBox *moov, int numtrack, int clock, namestrack namet){ //Track Header// moov->TrackBox[numtrack].TrackHeaderBox.creation_time = clock; moov->TrackBox[numtrack].TrackHeaderBox.modification_time = clock; moov->TrackBox[numtrack].TrackHeaderBox.track_ID = numtrack + 1; //From 0x00000001 - 0x7FFFFFFF (dec 2147483647) moov->TrackBox[numtrack].TrackHeaderBox.reserved = 0; // moov->TrackBox[numtrack].TrackHeaderBox.duration = getdurationtrack(); moov->TrackBox[numtrack].TrackHeaderBox.reserved2[0] = 0; moov->TrackBox[numtrack].TrackHeaderBox.reserved2[1] = 0; moov->TrackBox[numtrack].TrackHeaderBox.layer = 0; moov->TrackBox[numtrack].TrackHeaderBox.alternate_group = 0; moov->TrackBox[numtrack].TrackHeaderBox.volume = 1; moov->TrackBox[numtrack].TrackHeaderBox.reserved3 = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[0] = 0x00010000; moov->TrackBox[numtrack].TrackHeaderBox.matrix[1] = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[2] = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[3] = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[4] = 0x00010000; moov->TrackBox[numtrack].TrackHeaderBox.matrix[5] = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[6] = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[7] = 0; moov->TrackBox[numtrack].TrackHeaderBox.matrix[8] = 0x40000000; moov->TrackBox[numtrack].TrackHeaderBox.width = 0; //just for video moov->TrackBox[numtrack].TrackHeaderBox.height = 0; //just for video //Track reference box //No hint tracks at the moment. moov->TrackBox[numtrack].TrackReferenceBox.reference_type = 'cdsc'; moov->TrackBox[numtrack].TrackReferenceBox.track_ID = numtrack + 1; /* //Edit list box int entry_count,i; entry_count = getentrycount(); for (i=1; i<entry_count; i++) { moov->TrackBox[numtrack].EditListBox.segment_duration = 0; } */ //Media Box// //Media Header Box// moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.creation_time = clock; moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.modification_time = clock; moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.timescale = 60; // moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.duration = getdurationtrack(); moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.language[0] = 'a'; moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.language[1] = 'n'; moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.language[2] = 'g'; moov->TrackBox[numtrack].MediaBox.MediaHeaderBox.pre_defined = 0; //Handler Box// moov->TrackBox[numtrack].MediaBox.HandlerBox.pre_defined = 0; //If we want to introduce another type of track change here: moov->TrackBox[numtrack].MediaBox.HandlerBox.handler_type = 'soun'; moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[0] = 0; moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[1] = 0; moov->TrackBox[numtrack].MediaBox.HandlerBox.reserved[2] = 0; //Use the name from Media Data Box to store it in HandlerBox.name: strcpy(moov->TrackBox[numtrack].MediaBox.HandlerBox.name, namet[numtrack].title); //Media Information Box// //Sound Header Box // moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.balance = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SoundMediaHeaderBox.reserved = 0; //Hint Header Box// //In case of hint track follow the box /*moov->TrackBox[numtrack].MediaBox.MediaInformationBox.HintMediaHeaderBox.maxPDUsize = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.HintMediaHeaderBox.avgPDUsize = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.HintMediaHeaderBox.maxbitrate = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.HintMediaHeaderBox.avgbitrate = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.HintMediaHeaderBox.reserved = 0; */ //Data information Box// //In case we want add tracks located in the web int flag = 1; // means that the media data is in the same file.No string, not even empty one //shall ve suplied in the entry field. //If track is in URL add info here. //Just admit URL data moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.DataEntryUrlBox.flags = 1; if(flag == 0){ moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.DataEntryUrlBox.location = 0; //moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.DataEntryUrnBox.name = 0; //moov->TrackBox[numtrack].MediaBox.MediaInformationBox.DataInformationBox.DataEntryUrnBox.location = 0; } //el samplecontainer(moov, numtrack); } void samplecontainer(MovieBox *moov, int numtrack){ //Sample Table Box // int numdatareferences = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleEntry.reserved[0] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleEntry.reserved[1] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleEntry.reserved[2] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleEntry.reserved[3] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleEntry.reserved[4] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.SampleEntry.reserved[5] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. SampleEntry.format = 'wav'; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. SampleEntry.data_reference_index = numdatareferences; //Find more info //No hinttrack at the moment. moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.HintSampleEntry.data = 0; //BitRate // moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox. // BitRateBox.bufferSizeDB = sizetrack(); moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.BitRateBox .maxBitrate = 1411000; //In this case wav at 1441Kbps moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox.BitRateBox .avgBitrate = 1411000; //Sample description box moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .SampleDescriptionBox.handler_type = 'soun'; //Just audio! int i, entry; entry=1; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .SampleDescriptionBox.entry_count = entry; //Check this later!!! //No metadata and hint tracks, neither URI at the moment for (i=0; i<=entry; i++) { switch (moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .SampleDescriptionBox.handler_type) { case 'soun': //For audio tracks moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .AudioSampleEntry.reserved[0] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .AudioSampleEntry.reserved[1] = 0; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .AudioSampleEntry.channelcount = 1; //The tracks are mono. moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .AudioSampleEntry.samplesize = 16; moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .AudioSampleEntry.pre_defined = 0; //Ask Panos!! moov->TrackBox[numtrack].MediaBox.MediaInformationBox.SampleTableBox .AudioSampleEntry.samplerate = 441000; //44.1Khz break; case 'hint': //Hint tracks //HintSampleEntry(); break; case 'meta': //Metadata tracks // MetadataSampleEntry(); default: break; } } } void groupscontainer(MovieBox *moov){ int num, flg, i, j, numelem; char selectmode, groupname[30]; char* fmt = "%[^\n]%*c"; printf("Define the number of groups:\n"); fflush(stdin); scanf("%d",&num); moov->GroupContainerBox.num_groups = num; for (i=0; i<num; i++) { printf("Select mode of group %d:\n",i+1); printf("Mode | Display | Edit\n"); printf("---- | ------- | ----\n"); printf(" 1 | disable | disable\n"); printf(" 2 | enable | disable\n"); scanf("%d",&flg); getchar(); fflush(stdin); moov->GroupContainerBox.GroupBox[i].flags = flg; moov->GroupContainerBox.GroupBox[i].group_ID = 2147483648 + 1; // From 0x80000000 to 0xFFFFFFFF printf("Enter the name for group %d:\n", i+1); scanf(fmt,moov->GroupContainerBox.GroupBox[i].group_name); strcpy(groupname,moov->GroupContainerBox.GroupBox[i].group_name); printf("Enter a brief description for group %s:\n", groupname); scanf(fmt,moov->GroupContainerBox.GroupBox[i].group_description); moov->GroupContainerBox.GroupBox[i].num_elements = numelem; printf("Number of elements involved in group %d:\n", i+1); fflush(stdin); scanf("%d",&numelem); for (j=0; j<numelem; j++) { printf("Enter name for element %d of group %s\n",j+1,groupname); scanf("%s",moov->GroupContainerBox.GroupBox[i].element_ID[j]); // moov->GroupContainerBox.GroupBox[i].element_ID[j] = getelemID(); //Can be track or group } //printf("Select group activation mode:\n"); //scanf("%d",selectmode); selectmode = 0; moov->GroupContainerBox.GroupBox[i].group_activation_mode = selectmode; //Depends on rules. For now just 0. // if (selectmode == 2) { // moov->GroupContainerBox.GroupBox[i].group_activation_elements_number = 0; // } moov->GroupContainerBox.GroupBox[i].group_reference_volume = 1; } } void presetcontainer(MovieBox *moov){ int i, j, k, l, m, numpres=0, flag=0; int num_output_channel = 2; // Stereo char numelempres=0, prestype=0, namepres[30]; u16 globalvol=0, voltrack=0, num_updates =0 ; char* fmt = "%[^\n]%*c"; printf("Define the number of presets: (10 max)\n"); scanf("%d",&numpres); moov->PresetContainerBox.num_preset = numpres; moov->PresetContainerBox.default_preset_ID = 0; // Indicates initial preset activated. getchar(); fflush(stdin); for (i=0; i<numpres; i++) { printf("Enter name for the preset %d\n",i+1 ); fflush(stdin); scanf(fmt,namepres); strcpy(moov->PresetContainerBox.PresetBox[i].preset_name, namepres); printf("Select mode of preset %s:\n",namepres); printf("Mode | Display | Edit\n"); printf("---- | ------- | -------\n"); printf(" 1 | disable | disable\n"); printf(" 2 | enable | disable\n"); printf(" 3 | enable | enable\n"); scanf("%d",&flag); moov->PresetContainerBox.PresetBox[i].preset_ID = numpres+1; printf("Select type for preset %s:\n",namepres); printf("preset_type | Meaning\n"); printf("----------- | ---------------------------\n"); printf(" 0 | static track volume preset\n"); printf(" 1 | static object volume preset\n"); printf(" 2 | dynamic track volume preset\n"); printf(" 3 | dynamic object volume preset\n"); //scanf(" %c", &prestype); prestype = 0; moov->PresetContainerBox.PresetBox[i].preset_type = prestype; printf("Select the playback volume gain of preset output %d\n",i+1); printf(" index | 0 | 1 | 2 | 3 | ... | 149 | 150 |\n"); printf("value(ratio) | 0 |0.01 |0.02 |0.03 | ... |1.49 |1.50 |\n"); scanf("%d",&globalvol); printf("Gloval volume %d\n",globalvol); moov->PresetContainerBox.PresetBox[i].preset_global_volume = globalvol; printf("Enter number of elements in the preset: (10 max)\n"); scanf(" %c", &numelempres); moov->PresetContainerBox.PresetBox[i].num_preset_elements = numelempres; moov->PresetContainerBox.PresetBox[i].preset_element_ID[j] = numelempres +1; printf("Select the playback volume gain of element %d\n",k+1); printf(" index | 0 | 1 | 2 | 3 | ... | 199 | 200 |\n"); printf("value(ratio) | 0 |0.02 |0.04 |0.06 | ... |3.98 |4.00 |\n"); scanf("%d",&voltrack); if(prestype == 0){ for (j=1; j<numelempres; j++) { moov->PresetContainerBox.PresetBox[i].preset_volume_element[j] = voltrack; } } if(prestype == 1){ moov->PresetContainerBox.PresetBox[i].num_input_channel[j] = 2; //All tracks stereo moov->PresetContainerBox.PresetBox[i].output_channel_type = 2; for (j=1; j<numelempres; j++) { for (m=0; m<moov->PresetContainerBox.PresetBox[i].num_input_channel[j]; m++){ for (k=0; k<num_output_channel; k++){ moov->PresetContainerBox.PresetBox[i].preset_volume_element[j] = voltrack; } } } } if(prestype == 2){ // dynamic track volume preset moov->PresetContainerBox.PresetBox[i].num_updates = num_updates; //No updates for the moment for(l=0; l<num_updates; l++){ moov->PresetContainerBox.PresetBox[i].update_sample_number = 0; for(j=0; j<numelempres; j++){ moov->PresetContainerBox.PresetBox[i].preset_volume_element[j] = voltrack; } } } if(prestype == 3){ // dynamic object volume preset moov->PresetContainerBox.PresetBox[i].num_updates = num_updates; //No updates for the moment moov->PresetContainerBox.PresetBox[i].num_input_channel[j] = 2; //All tracks stereo moov->PresetContainerBox.PresetBox[i].output_channel_type = 2; for(l=0; l<num_updates; l++){ moov->PresetContainerBox.PresetBox[i].update_sample_number = 0; for(j=0; j<numelempres; j++){ for (k=0; k<num_output_channel; k++){ moov->PresetContainerBox.PresetBox[i].preset_volume_element[j] = voltrack; } } } } } } void metadata(MetaBox *meta){ int find = 0, i, j; char coc[4]; meta->theHandler.pre_defined = 0; printf("Enter type of metadata:\n"); printf("'soun' 'hint' 'meta'\n"); fflush(stdin); scanf("%s", &coc); while (find == 0) { if (strcmp("soun", coc)==0) { meta->theHandler.handler_type = 'soun'; find = 1; } if (strcmp("hint", coc)==0) { meta->theHandler.handler_type = 'hint'; find = 1; } if (strcmp("meta", coc)==0) { meta->theHandler.handler_type = 'meta'; find = 1; } if (find == 0) { printf("Type unknown, please enter type:\n"); printf("'soun' 'hint' 'meta'\n"); scanf("%s", &coc); } } printf("%d\n", meta->theHandler.handler_type); meta->theHandler.reserved[0] = 0; meta->theHandler.reserved[1] = 0; meta->theHandler.reserved[2] = 0; printf("Name:\n"); fflush(stdin); scanf("%s", meta->theHandler.name); //In case items are stored online: //meta->dinfo = ....; //Item location box //Size = Index_Size(4), base_offset_size(4),length(4),offset(4) = 16 bits //Each one has size 0, 4 or 8. //Assume same size for all = 8.It can be different meta->ItemLocationBox.Size = 0x4444; meta->ItemLocationBox.item_count = 0; for (i=0; i<meta->ItemLocationBox.item_count; i++) { //Check the value!!! I don't understand. meta->ItemLocationBox.c_method = 0x0001; //=0 Taken from field, 1(idat) or 2(item) } //These values have to be rechecked meta->ItemLocationBox.data_reference_index = 0; //In this file meta->ItemLocationBox.base_offset = 0; //Check value!!! meta->ItemLocationBox.extent_count = 1; for (j=0; j<meta->ItemLocationBox.extent_count; j++) { meta->ItemLocationBox.extent_index = 1; } meta->ItemLocationBox.extent_offset = 0; meta->ItemLocationBox.extent_length = 0; //Rest of the parameters }