//写入AAC信息 bool EasyMP4Writer::WriteAACInfo(unsigned char*info,int len, int nSampleRate, int nChannel, int nBitsPerSample) { p_audiosample=gf_isom_sample_new(); p_audiosample->data=(char*)malloc(1024*10); GF_ESD*esd= gf_odf_desc_esd_new(0); esd->ESID=gf_isom_get_track_id(p_file,m_audiotrackid); esd->OCRESID=gf_isom_get_track_id(p_file,m_audiotrackid); esd->decoderConfig->streamType=0x05; esd->decoderConfig->objectTypeIndication=0x40;//0x40; esd->slConfig->timestampResolution=1000;//1000;//时间单元 esd->decoderConfig->decoderSpecificInfo=(GF_DefaultDescriptor*)gf_odf_desc_new(GF_ODF_DSI_TAG); esd->decoderConfig->decoderSpecificInfo->data=(char*)malloc(len); memcpy(esd->decoderConfig->decoderSpecificInfo->data,info,len); esd->decoderConfig->decoderSpecificInfo->dataLength=len; GF_Err gferr=gf_isom_new_mpeg4_description(p_file, m_audiotrackid, esd, NULL, NULL, &i_audiodescidx); if (gferr!=0) { // TRACE("mpeg4_description:%d\n",gferr); } gferr=gf_isom_set_audio_info(p_file,m_audiotrackid,i_audiodescidx, nSampleRate,nChannel, nBitsPerSample);//44100 2 16 if (gferr!=0) { // TRACE("gf_isom_set_audio:%d\n",gferr); } free(esd->decoderConfig->decoderSpecificInfo->data); return true; }
static GF_Err ISOW_Write(GF_StreamingCache *mc, LPNETCHANNEL ch, char *data, u32 data_size, GF_SLHeader *sl_hdr) { ISOMChannel *mch; GF_ESD *esd; u32 di, mtype; u64 DTS, CTS; ISOMReader *cache = (ISOMReader *)mc->priv; if (!cache->mov || !cache->service) return GF_BAD_PARAM; mch = isor_get_channel(cache, ch); if (!mch) { Bool mapped; GF_NetworkCommand com; com.base.on_channel = ch; com.base.command_type = GF_NET_CHAN_GET_ESD; gf_service_command(cache->service, &com, GF_OK); if (!com.cache_esd.esd) return GF_SERVICE_ERROR; esd = (GF_ESD *)com.cache_esd.esd; switch (esd->decoderConfig->streamType) { case GF_STREAM_OD: mtype = GF_ISOM_MEDIA_OD; break; case GF_STREAM_SCENE: mtype = GF_ISOM_MEDIA_SCENE; break; case GF_STREAM_VISUAL: mtype = GF_ISOM_MEDIA_VISUAL; break; case GF_STREAM_AUDIO: mtype = GF_ISOM_MEDIA_AUDIO; break; case GF_STREAM_MPEG7: mtype = GF_ISOM_MEDIA_MPEG7; break; case GF_STREAM_OCI: mtype = GF_ISOM_MEDIA_OCI; break; case GF_STREAM_IPMP: mtype = GF_ISOM_MEDIA_IPMP; break; case GF_STREAM_MPEGJ: mtype = GF_ISOM_MEDIA_MPEGJ; break; case GF_STREAM_TEXT: mtype = GF_ISOM_MEDIA_TEXT; break; default: return GF_NOT_SUPPORTED; } GF_SAFEALLOC(mch, ISOMChannel); if (!mch) { return GF_OUT_OF_MEM; } mch->time_scale = esd->slConfig->timestampResolution; mch->streamType = esd->decoderConfig->streamType; mch->track = gf_isom_new_track(cache->mov, com.cache_esd.esd->ESID, mtype, mch->time_scale); mch->is_playing = GF_TRUE; mch->channel = ch; mch->owner = cache; gf_isom_set_track_enabled(cache->mov, mch->track, 1); /*translate 3GP streams to MP4*/ mapped = GF_FALSE; if (esd->decoderConfig->objectTypeIndication==GPAC_OTI_MEDIA_GENERIC) { char szCode[5]; strncpy(szCode, esd->decoderConfig->decoderSpecificInfo->data, 4); szCode[4]=0; if (!stricmp(szCode, "samr") || !stricmp(szCode, "amr ") || !stricmp(szCode, "sawb")) { GF_3GPConfig amrc; mapped = GF_TRUE; memset(&amrc, 0, sizeof(GF_3GPConfig)); amrc.frames_per_sample = (u32) esd->decoderConfig->decoderSpecificInfo->data[13]; amrc.type = (!stricmp(szCode, "sawb")) ? GF_ISOM_SUBTYPE_3GP_AMR_WB : GF_ISOM_SUBTYPE_3GP_AMR; amrc.vendor = GF_VENDOR_GPAC; gf_isom_3gp_config_new(cache->mov, mch->track, &amrc, NULL, NULL, &di); } else if (!stricmp(szCode, "h263")) { GF_3GPConfig h263c; memset(&h263c, 0, sizeof(GF_3GPConfig)); h263c.type = GF_ISOM_SUBTYPE_3GP_H263; h263c.vendor = GF_VENDOR_GPAC; gf_isom_3gp_config_new(cache->mov, mch->track, &h263c, NULL, NULL, &di); mapped = GF_TRUE; } } if (!mapped) gf_isom_new_mpeg4_description(cache->mov, mch->track, esd, NULL, NULL, &di); if (com.cache_esd.is_iod_stream) gf_isom_add_track_to_root_od(cache->mov, mch->track); gf_list_add(cache->channels, mch); } /*first sample, cache it*/ if (!mch->cache_sample) { mch->cache_seed_ts = sl_hdr->decodingTimeStamp; mch->cache_sample = gf_isom_sample_new(); mch->cache_sample->IsRAP = sl_hdr->randomAccessPointFlag; mch->cache_sample->dataLength = data_size; mch->cache_sample->data = (char*)gf_malloc(sizeof(char)*data_size); memcpy(mch->cache_sample->data, data, sizeof(char)*data_size); return GF_OK; } /*adjust DTS/CTS*/ DTS = sl_hdr->decodingTimeStamp - mch->cache_seed_ts; if ((mch->streamType==GF_STREAM_VISUAL) && (DTS<=mch->cache_sample->DTS)) { assert(DTS>mch->prev_dts); CTS = mch->cache_sample->DTS + mch->cache_sample->CTS_Offset; mch->cache_sample->CTS_Offset = 0; /*first time, shift all CTS*/ if (!mch->frame_cts_offset) { u32 i, count = gf_isom_get_sample_count(cache->mov, mch->track); mch->frame_cts_offset = (u32) (DTS-mch->prev_dts); for (i=0; i<count; i++) { gf_isom_modify_cts_offset(cache->mov, mch->track, i+1, mch->frame_cts_offset); } mch->cache_sample->CTS_Offset += mch->frame_cts_offset; } mch->cache_sample->DTS = mch->prev_dts + mch->frame_cts_offset; mch->cache_sample->CTS_Offset += (u32) (CTS-mch->cache_sample->DTS); } /*deal with reference picture insertion: if no CTS offset and biggest CTS until now, this is a reference insertion - we must check that in order to make sure we have strictly increasing DTSs*/ if (mch->max_cts && !mch->cache_sample->CTS_Offset && (mch->cache_sample->DTS+mch->cache_sample->CTS_Offset > mch->max_cts)) { assert(mch->cache_sample->DTS > mch->prev_dts + mch->frame_cts_offset); CTS = mch->cache_sample->DTS + mch->cache_sample->CTS_Offset; mch->cache_sample->DTS = mch->prev_dts + mch->frame_cts_offset; mch->cache_sample->CTS_Offset = (u32) (CTS-mch->cache_sample->DTS); } if (mch->cache_sample->CTS_Offset) mch->max_cts = mch->cache_sample->DTS+mch->cache_sample->CTS_Offset; /*add cache*/ gf_isom_add_sample(cache->mov, mch->track, 1, mch->cache_sample); assert(!mch->prev_dts || (mch->prev_dts < mch->cache_sample->DTS)); mch->prev_dts = mch->cache_sample->DTS; mch->duration = MAX(mch->max_cts, mch->prev_dts); gf_isom_sample_del(&mch->cache_sample); /*store sample*/ mch->cache_sample = gf_isom_sample_new(); mch->cache_sample->IsRAP = sl_hdr->randomAccessPointFlag; mch->cache_sample->DTS = DTS + mch->frame_cts_offset; mch->cache_sample->CTS_Offset = (u32) (sl_hdr->compositionTimeStamp - mch->cache_seed_ts - DTS); mch->cache_sample->dataLength = data_size; mch->cache_sample->data = (char*)gf_malloc(sizeof(char)*data_size); memcpy(mch->cache_sample->data, data, sizeof(char)*data_size); return GF_OK; }
int main(int argc, char **argv) { GF_ISOFile *movie; GF_ESD *esd; GF_Err e; Double gb_size = 5.0; u8 store_mode; u32 track, di, i, nb_samp; GF_ISOSample *samp; store_mode = GF_ISOM_OPEN_WRITE; for (i=1; i<argc; i++) { if (!strcmp(argv[i], "-flat")) store_mode = GF_ISOM_OPEN_WRITE; else if (!strcmp(argv[i], "-inter")) store_mode = GF_ISOM_WRITE_EDIT; else if (!strcmp(argv[i], "-size") && (i+1<argc)) { gb_size = atof(argv[i+1]); i++; } else if (!strcmp(argv[i], "-h")) { PrintUsage(); return 0; } } nb_samp = (u32) (gb_size*1024); fprintf(stdout, "Creating test file %s - %g GBytes - %d samples - %s mode\n", TEST_FILE_NAME, gb_size, nb_samp, (store_mode == GF_ISOM_OPEN_WRITE) ? "Flat" : "Interleaved"); movie = gf_isom_open(TEST_FILE_NAME, store_mode, NULL); if (!movie) { fprintf(stdout, "Error creating file: %s\n", gf_error_to_string(gf_isom_last_error(NULL))); return 1; } track = gf_isom_new_track(movie, 1, GF_ISOM_MEDIA_VISUAL, 25); esd = gf_odf_desc_esd_new(2); esd->decoderConfig->streamType = 4; gf_isom_new_mpeg4_description(movie, track, esd, NULL, NULL, &di); samp = gf_isom_sample_new(); samp->dataLength = 1024*1024; samp->data = gf_malloc(sizeof(char)*samp->dataLength); memset(samp->data, 0, sizeof(char)*samp->dataLength); for (i=0; i<nb_samp; i++) { if (samp->DTS % 25) samp->IsRAP = 0; else samp->IsRAP = 1; e = gf_isom_add_sample(movie, track, di, samp); samp->DTS += 1; fprintf(stdout, "Writing sample %d / %d \r", i+1, nb_samp); if (e) break; } gf_isom_sample_del(&samp); if (e) { fprintf(stdout, "\nError writing sample %d\n", i); gf_isom_delete(movie); return 1; } fprintf(stdout, "\nDone writing samples\n"); e = gf_isom_close(movie); if (e) { fprintf(stdout, "Error writing file\n"); return 1; } return 0; }
int dc_gpac_audio_moov_create(AudioOutputFile *audio_output_file, char *filename) { GF_Err ret; u32 di, track; u8 bpsample; GF_ESD *esd; #ifndef GPAC_DISABLE_AV_PARSERS GF_M4ADecSpecInfo acfg; #endif AVCodecContext *audio_codec_ctx = audio_output_file->codec_ctx; audio_output_file->isof = gf_isom_open(filename, GF_ISOM_OPEN_WRITE, NULL); if (!audio_output_file->isof) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot open iso file %s\n", filename)); return -1; } esd = gf_odf_desc_esd_new(2); if (!esd) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot create GF_ESD\n")); return -1; } esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); esd->decoderConfig->streamType = GF_STREAM_AUDIO; if (!strcmp(audio_output_file->codec_ctx->codec->name, "aac")) { //TODO: find an automatic table esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4; esd->decoderConfig->bufferSizeDB = 20; esd->slConfig->timestampResolution = audio_codec_ctx->sample_rate; esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); esd->ESID = 1; #ifndef GPAC_DISABLE_AV_PARSERS memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo)); acfg.base_object_type = GF_M4A_AAC_LC; acfg.base_sr = audio_codec_ctx->sample_rate; acfg.nb_chan = audio_codec_ctx->channels; acfg.sbr_object_type = 0; acfg.audioPL = gf_m4a_get_profile(&acfg); ret = gf_m4a_write_config(&acfg, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength); assert(ret == GF_OK); #endif } else { if (strcmp(audio_output_file->codec_ctx->codec->name, "mp2")) { GF_LOG(GF_LOG_WARNING, GF_LOG_DASH, ("Unlisted codec, setting GPAC_OTI_AUDIO_MPEG1 descriptor.\n")); } esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1; esd->decoderConfig->bufferSizeDB = 20; esd->slConfig->timestampResolution = audio_codec_ctx->sample_rate; esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); esd->ESID = 1; #ifndef GPAC_DISABLE_AV_PARSERS memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo)); acfg.base_object_type = GF_M4A_LAYER2; acfg.base_sr = audio_codec_ctx->sample_rate; acfg.nb_chan = audio_codec_ctx->channels; acfg.sbr_object_type = 0; acfg.audioPL = gf_m4a_get_profile(&acfg); ret = gf_m4a_write_config(&acfg, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength); assert(ret == GF_OK); #endif } //gf_isom_store_movie_config(video_output_file->isof, 0); track = gf_isom_new_track(audio_output_file->isof, esd->ESID, GF_ISOM_MEDIA_AUDIO, audio_codec_ctx->sample_rate); GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("TimeScale: %d \n", audio_codec_ctx->time_base.den)); if (!track) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("Cannot create new track\n")); return -1; } ret = gf_isom_set_track_enabled(audio_output_file->isof, track, 1); if (ret != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_set_track_enabled\n", gf_error_to_string(ret))); return -1; } // if (!esd->ESID) esd->ESID = gf_isom_get_track_id(audio_output_file->isof, track); ret = gf_isom_new_mpeg4_description(audio_output_file->isof, track, esd, NULL, NULL, &di); if (ret != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_new_mpeg4_description\n", gf_error_to_string(ret))); return -1; } gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; bpsample = av_get_bytes_per_sample(audio_output_file->codec_ctx->sample_fmt) * 8; ret = gf_isom_set_audio_info(audio_output_file->isof, track, di, audio_codec_ctx->sample_rate, audio_output_file->codec_ctx->channels, bpsample); if (ret != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_set_audio_info\n", gf_error_to_string(ret))); return -1; } #ifndef GPAC_DISABLE_AV_PARSERS ret = gf_isom_set_pl_indication(audio_output_file->isof, GF_ISOM_PL_AUDIO, acfg.audioPL); if (ret != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_set_pl_indication\n", gf_error_to_string(ret))); return -1; } #endif GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("time scale: %d sample dur: %d \n", audio_codec_ctx->time_base.den, audio_output_file->codec_ctx->frame_size)); ret = gf_isom_setup_track_fragment(audio_output_file->isof, track, 1, audio_output_file->codec_ctx->frame_size, 0, 0, 0, 0); if (ret != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_setup_track_fragment\n", gf_error_to_string(ret))); return -1; } //gf_isom_add_track_to_root_od(video_output_file->isof,1); ret = gf_isom_finalize_for_fragment(audio_output_file->isof, 1); if (ret != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_finalize_for_fragment\n", gf_error_to_string(ret))); return -1; } ret = gf_media_get_rfc_6381_codec_name(audio_output_file->isof, track, audio_output_file->audio_data_conf->codec6381, GF_FALSE, GF_FALSE); if (ret != GF_OK) return -1; return 0; }
int dc_gpac_audio_moov_create(AudioOutputFile * p_aoutf, char * psz_name) { GF_Err ret; AVCodecContext * p_audio_codec_ctx = p_aoutf->p_codec_ctx; u32 di; u32 track; GF_M4ADecSpecInfo acfg; p_aoutf->p_isof = gf_isom_open(psz_name, GF_ISOM_OPEN_WRITE, NULL); if (!p_aoutf->p_isof) { fprintf(stderr, "Cannot open iso file %s\n", psz_name); return -1; } memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo)); acfg.base_object_type = GF_M4A_AAC_LC; acfg.base_sr = p_audio_codec_ctx->sample_rate; acfg.nb_chan = p_audio_codec_ctx->channels; acfg.sbr_object_type = 0; acfg.audioPL = gf_m4a_get_profile(&acfg); GF_ESD * p_esd = gf_odf_desc_esd_new(2); if (!p_esd) { fprintf(stderr, "Cannot create GF_ESD\n"); return -1; } p_esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); p_esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); p_esd->decoderConfig->streamType = GF_STREAM_AUDIO; p_esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4; p_esd->decoderConfig->bufferSizeDB = 20; p_esd->slConfig->timestampResolution = p_audio_codec_ctx->sample_rate; p_esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); p_esd->ESID = 1; ret = gf_m4a_write_config(&acfg, &p_esd->decoderConfig->decoderSpecificInfo->data, &p_esd->decoderConfig->decoderSpecificInfo->dataLength); //gf_isom_store_movie_config(p_voutf->p_isof, 0); track = gf_isom_new_track(p_aoutf->p_isof, p_esd->ESID, GF_ISOM_MEDIA_AUDIO, p_audio_codec_ctx->sample_rate); //printf("TimeScale: %d \n", p_video_codec_ctx->time_base.den); if (!track) { fprintf(stderr, "Cannot create new track\n"); return -1; } ret = gf_isom_set_track_enabled(p_aoutf->p_isof, track, 1); if (ret != GF_OK) { fprintf(stderr, "%s: gf_isom_set_track_enabled\n", gf_error_to_string(ret)); return -1; } // if (!p_esd->ESID) p_esd->ESID = gf_isom_get_track_id(p_aoutf->p_isof, track); ret = gf_isom_new_mpeg4_description(p_aoutf->p_isof, track, p_esd, NULL, NULL, &di); if (ret != GF_OK) { fprintf(stderr, "%s: gf_isom_new_mpeg4_description\n", gf_error_to_string(ret)); return -1; } gf_odf_desc_del((GF_Descriptor *) p_esd); p_esd = NULL; u8 bpsample = av_get_bytes_per_sample(p_aoutf->p_codec_ctx->sample_fmt) * 8; ret = gf_isom_set_audio_info(p_aoutf->p_isof, track, di, p_audio_codec_ctx->sample_rate, p_aoutf->p_codec_ctx->channels, bpsample); if (ret != GF_OK) { fprintf(stderr, "%s: gf_isom_set_audio_info\n", gf_error_to_string(ret)); return -1; } ret = gf_isom_set_pl_indication(p_aoutf->p_isof, GF_ISOM_PL_AUDIO, acfg.audioPL); if (ret != GF_OK) { fprintf(stderr, "%s: gf_isom_set_pl_indication\n", gf_error_to_string(ret)); return -1; } //printf("time scale: %d sample dur: %d \n", // p_video_codec_ctx->time_base.den, p_aoutf->p_codec_ctx->frame_size); ret = gf_isom_setup_track_fragment(p_aoutf->p_isof, track, 1, p_aoutf->p_codec_ctx->frame_size, 0, 0, 0, 0); if (ret != GF_OK) { fprintf(stderr, "%s: gf_isom_setup_track_fragment\n", gf_error_to_string(ret)); return -1; } //gf_isom_add_track_to_root_od(p_voutf->p_isof,1); ret = gf_isom_finalize_for_fragment(p_aoutf->p_isof, 1); if (ret != GF_OK) { fprintf(stderr, "%s: gf_isom_finalize_for_fragment\n", gf_error_to_string(ret)); return -1; } return 0; }