📄 media_export.c
字号:
/*write header*/ /*'NHnt' format*/ gf_bs_write_data(bs, "NHnt", 4); /*version 1*/ gf_bs_write_u8(bs, 0); /*streamType*/ gf_bs_write_u8(bs, esd->decoderConfig->streamType); /*OTI*/ gf_bs_write_u8(bs, esd->decoderConfig->objectTypeIndication); /*reserved*/ gf_bs_write_u16(bs, 0); /*bufferDB*/ gf_bs_write_u24(bs, esd->decoderConfig->bufferSizeDB); /*avg BitRate*/ gf_bs_write_u32(bs, esd->decoderConfig->avgBitrate); /*max bitrate*/ gf_bs_write_u32(bs, esd->decoderConfig->maxBitrate); /*timescale*/ gf_bs_write_u32(bs, esd->slConfig->timestampResolution); gf_odf_desc_del((GF_Descriptor *) esd); has_b_frames = gf_isom_has_time_offset(dumper->file, track); pos = 0; count = gf_isom_get_sample_count(dumper->file, track); for (i=0; i<count; i++) { GF_ISOSample *samp = gf_isom_get_sample(dumper->file, track, i+1, &di); if (!samp) break; fwrite(samp->data, samp->dataLength, 1, out_med); /*dump nhnt info*/ gf_bs_write_u24(bs, samp->dataLength); gf_bs_write_int(bs, samp->IsRAP, 1); /*AU start & end flag always true*/ gf_bs_write_int(bs, 1, 1); gf_bs_write_int(bs, 1, 1); /*reserved*/ gf_bs_write_int(bs, 0, 3); /*type - try to guess it*/ if (has_b_frames) { if (samp->IsRAP) gf_bs_write_int(bs, 0, 2); /*if CTS offset, assime P*/ else if (samp->CTS_Offset) gf_bs_write_int(bs, 1, 2); else gf_bs_write_int(bs, 2, 2); } else { gf_bs_write_int(bs, samp->IsRAP ? 0 : 1, 2); } gf_bs_write_u32(bs, pos); /*TODO support for large files*/ gf_bs_write_u32(bs, (u32) (samp->DTS + samp->CTS_Offset) ); gf_bs_write_u32(bs, (u32) samp->DTS); pos += samp->dataLength; gf_isom_sample_del(&samp); gf_set_progress("NHNT Export", i+1, count); if (dumper->flags & GF_EXPORT_DO_ABORT) break; } fclose(out_med); gf_bs_del(bs); fclose(out_nhnt); return GF_OK;}static GF_Err MP4T_CopyTrack(GF_MediaExporter *dumper, GF_ISOFile *infile, u32 inTrackNum, GF_ISOFile *outfile, Bool ResetDependancies, Bool AddToIOD){ GF_ESD *esd; GF_InitialObjectDescriptor *iod; u32 TrackID, newTk, descIndex, i, ts, rate, pos, di, count, msubtype; u64 dur; GF_ISOSample *samp; if (!inTrackNum) { if (gf_isom_get_track_count(infile) != 1) return gf_export_message(dumper, GF_BAD_PARAM, "Please specify trackID to export"); inTrackNum = 1; } //check the ID is available TrackID = gf_isom_get_track_id(infile, inTrackNum); newTk = gf_isom_get_track_by_id(outfile, TrackID); if (newTk) TrackID = 0; //get the ESD and remove dependancies esd = NULL; msubtype = gf_isom_get_media_subtype(infile, inTrackNum, 1); if (msubtype == GF_ISOM_SUBTYPE_MPEG4) { esd = gf_isom_get_esd(infile, inTrackNum, 1); if (esd && ResetDependancies) { esd->dependsOnESID = 0; esd->OCRESID = 0; } } newTk = gf_isom_new_track(outfile, TrackID, gf_isom_get_media_type(infile, inTrackNum), gf_isom_get_media_timescale(infile, inTrackNum)); gf_isom_set_track_enabled(outfile, newTk, 1); if (esd) { gf_isom_new_mpeg4_description(outfile, newTk, esd, NULL, NULL, &descIndex); if ((esd->decoderConfig->streamType == GF_STREAM_VISUAL) || (esd->decoderConfig->streamType == GF_STREAM_SCENE)) { u32 w, h; gf_isom_get_visual_info(infile, inTrackNum, 1, &w, &h); /*this is because so many files have reserved values of 320x240 from v1 ... */ if ((esd->decoderConfig->objectTypeIndication == 0x20) ) { GF_M4VDecSpecInfo dsi; gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); w = dsi.width; h = dsi.height; } gf_isom_set_visual_info(outfile, newTk, 1, w, h); } else if ((esd->decoderConfig->streamType == GF_STREAM_ND_SUBPIC) && (esd->decoderConfig->objectTypeIndication == 0xe0)) { u32 w, h; s32 trans_x, trans_y; s16 layer; gf_isom_get_track_layout_info(infile, inTrackNum, &w, &h, &trans_x, &trans_y, &layer); gf_isom_set_track_layout_info(outfile, newTk, w << 16, h << 16, trans_x, trans_y, layer); } esd->decoderConfig->avgBitrate = 0; esd->decoderConfig->maxBitrate = 0; } else { gf_isom_clone_sample_description(outfile, newTk, infile, inTrackNum, 1, NULL, NULL, &descIndex); } pos = 0; rate = 0; ts = gf_isom_get_media_timescale(infile, inTrackNum); count = gf_isom_get_sample_count(infile, inTrackNum); for (i=0; i<count; i++) { samp = gf_isom_get_sample(infile, inTrackNum, i+1, &di); gf_isom_add_sample(outfile, newTk, descIndex, samp); if (esd) { rate += samp->dataLength; esd->decoderConfig->avgBitrate += samp->dataLength; if (esd->decoderConfig->bufferSizeDB<samp->dataLength) esd->decoderConfig->bufferSizeDB = samp->dataLength; if (samp->DTS - pos > ts) { if (esd->decoderConfig->maxBitrate<rate) esd->decoderConfig->maxBitrate = rate; rate = 0; pos = 0; } } gf_isom_sample_del(&samp); gf_set_progress("ISO File Export", i, count); } gf_set_progress("ISO File Export", count, count); if (msubtype == GF_ISOM_SUBTYPE_MPEG4_CRYP) { esd = gf_isom_get_esd(infile, inTrackNum, 1); } else if (msubtype == GF_ISOM_SUBTYPE_AVC_H264) { return gf_isom_set_pl_indication(outfile, GF_ISOM_PL_VISUAL, 0x0F); } /*likely 3gp or any non-MPEG-4 isomedia file*/ else if (!esd) return gf_isom_remove_root_od(outfile); dur = gf_isom_get_media_duration(outfile, newTk); if (!dur) dur = ts; esd->decoderConfig->maxBitrate *= 8; esd->decoderConfig->avgBitrate = (u32) (esd->decoderConfig->avgBitrate * 8 * ts / dur); gf_isom_change_mpeg4_description(outfile, newTk, 1, esd); iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(infile); switch (esd->decoderConfig->streamType) { case GF_STREAM_SCENE: if (iod && (iod->tag==GF_ODF_IOD_TAG)) { gf_isom_set_pl_indication(outfile, GF_ISOM_PL_SCENE, iod->scene_profileAndLevel); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_GRAPHICS, iod->graphics_profileAndLevel); } else if (esd->decoderConfig->objectTypeIndication==0x20) { gf_export_message(dumper, GF_OK, "Warning: Scene PLs not found in original MP4 - defaulting to No Profile Specified"); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_SCENE, 0xFE); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_GRAPHICS, 0xFE); } break; case GF_STREAM_VISUAL: if (iod && (iod->tag==GF_ODF_IOD_TAG)) { gf_isom_set_pl_indication(outfile, GF_ISOM_PL_VISUAL, iod->visual_profileAndLevel); } else if (esd->decoderConfig->objectTypeIndication==0x20) { GF_M4VDecSpecInfo dsi; gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_VISUAL, dsi.VideoPL); } else { gf_export_message(dumper, GF_OK, "Warning: Visual PLs not found in original MP4 - defaulting to No Profile Specified"); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_VISUAL, 0xFE); } break; case GF_STREAM_AUDIO: if (iod && (iod->tag==GF_ODF_IOD_TAG)) { gf_isom_set_pl_indication(outfile, GF_ISOM_PL_AUDIO, iod->audio_profileAndLevel); } else if (esd->decoderConfig->objectTypeIndication==0x40) { GF_M4ADecSpecInfo cfg; gf_m4a_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &cfg); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_AUDIO, cfg.audioPL); } else { gf_export_message(dumper, GF_OK, "Warning: Audio PLs not found in original MP4 - defaulting to No Profile Specified"); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_AUDIO, 0xFE); } default: break; } if (iod) gf_odf_desc_del((GF_Descriptor *) iod); gf_odf_desc_del((GF_Descriptor *)esd); if (AddToIOD) gf_isom_add_track_to_root_od(outfile, newTk); return GF_OK;}GF_Err gf_media_export_isom(GF_MediaExporter *dumper){ GF_ISOFile *outfile; GF_Err e; Bool add_to_iod; char szName[1000], *ext; u32 track; u8 mode; track = gf_isom_get_track_by_id(dumper->file, dumper->trackID); if (gf_isom_get_media_type(dumper->file, dumper->trackID)==GF_ISOM_MEDIA_OD) { return gf_export_message(dumper, GF_BAD_PARAM, "Cannot extract OD track, result is meaningless"); } if (dumper->flags & GF_EXPORT_PROBE_ONLY) { dumper->flags |= GF_EXPORT_MERGE; return GF_OK; } ext = (char *) gf_isom_get_filename(dumper->file); if (ext) ext = strrchr(ext, '.'); sprintf(szName, "%s%s", dumper->out_name, ext ? ext : ".mp4"); add_to_iod = 1; mode = GF_ISOM_WRITE_EDIT; if (dumper->flags & GF_EXPORT_MERGE) { FILE *t = fopen(szName, "rb"); if (t) { add_to_iod = 0; mode = GF_ISOM_OPEN_EDIT; fclose(t); } } outfile = gf_isom_open(szName, mode, NULL); if (mode == GF_ISOM_WRITE_EDIT) { gf_isom_set_pl_indication(outfile, GF_ISOM_PL_AUDIO, 0xFF); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_VISUAL, 0xFF); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_GRAPHICS, 0xFF); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_SCENE, 0xFF); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_OD, 0xFF); gf_isom_set_pl_indication(outfile, GF_ISOM_PL_MPEGJ, 0xFF); } e = MP4T_CopyTrack(dumper, dumper->file, track, outfile, 1, add_to_iod); if (!add_to_iod) { u32 i; for (i=0; i<gf_isom_get_track_count(outfile); i++) { gf_isom_remove_track_from_root_od(outfile, i+1); } } if (e) gf_isom_delete(outfile); else gf_isom_close(outfile); return e;}GF_Err gf_media_export_avi(GF_MediaExporter *dumper){ GF_ESD *esd; GF_ISOSample *samp; char szName[1000], *v4CC; avi_t *avi_out; char dumdata[1]; u32 track, i, di, count, w, h, frame_d; GF_M4VDecSpecInfo dsi; Double FPS; track = gf_isom_get_track_by_id(dumper->file, dumper->trackID); esd = gf_isom_get_esd(dumper->file, track, 1); if (!esd) return gf_export_message(dumper, GF_NON_COMPLIANT_BITSTREAM, "Invalid MPEG-4 stream in track ID %d", dumper->trackID); if ((esd->decoderConfig->streamType!=GF_STREAM_VISUAL) || ( (esd->decoderConfig->objectTypeIndication!=0x20) && (esd->decoderConfig->objectTypeIndication!=0x21)) ) { gf_odf_desc_del((GF_Descriptor*)esd); return gf_export_message(dumper, GF_NON_COMPLIANT_BITSTREAM, "Track ID %d is not MPEG-4 Visual - cannot extract to AVI", dumper->trackID); } if (!esd->decoderConfig->decoderSpecificInfo) { gf_odf_desc_del((GF_Descriptor*)esd); return gf_export_message(dumper, GF_NON_COMPLIANT_BITSTREAM, "Missing decoder config for track ID %d", dumper->trackID); } if (dumper->flags & GF_EXPORT_PROBE_ONLY) return GF_OK; sprintf(szName, "%s.avi", dumper->out_name); avi_out = AVI_open_output_file(szName); if (!avi_out) { gf_odf_desc_del((GF_Descriptor *)esd); return gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName); } /*compute FPS - note we assume constant frame rate without droped frames...*/ count = gf_isom_get_sample_count(dumper->file, track); FPS = gf_isom_get_media_timescale(dumper->file, track); FPS *= (count-1); samp = gf_isom_get_sample(dumper->file, track, count, &di); FPS /= (s64) samp->DTS; gf_isom_sample_del(&samp); frame_d = 0; /*AVC - FIXME dump format is probably wrong...*/ if (esd->decoderConfig->objectTypeIndication==0x21) { gf_isom_get_visual_info(dumper->file, track, 1, &w, &h); v4CC = "h264"; } /*MPEG4*/ else { /*ignore visual size info, get it from dsi*/ gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); w = dsi.width; h = dsi.height; v4CC = "XVID"; /*compute VfW delay*/ if (gf_isom_has_time_offset(dumper->file, track)) { u32 max_CTSO; u64 DTS; DTS = max_CTSO = 0; for (i=0; i<count; i++) { samp = gf_isom_get_sample_info(dumper->file, track, i+1, NULL, NULL); if (!samp) break; if (samp->CTS_Offset>max_CTSO) max_CTSO = samp->CTS_Offset; DTS = samp->DTS; gf_isom_sample_del(&samp); } DTS /= (count-1); frame_d = max_CTSO / (u32) DTS; frame_d -= 1; /*dummy delay frame for xvid unpacked bitstreams*/ dumdata[0] = 127; } } gf_export_message(dumper, GF_OK, "Creating AVI file %d x %d @ %.2f FPS - 4CC \"%s\"", w, h, FPS,v4CC); if (frame_d) gf_export_message(dumper, GF_OK, "B-Frames detected - using unpacked bitstream with max B-VOP delta %d", frame_d); AVI_set_video(avi_out, w, h, FPS, v4CC); for (i=0; i<count; i++) { samp = gf_isom_get_sample(dumper->file, track, i+1, &di); if (!samp) break; /*add DSI before each I-frame in MPEG-4 SP*/ if (samp->IsRAP && (esd->decoderConfig->objectTypeIndication==0x20)) { char *data = (char*) malloc(sizeof(char) * (samp->dataLength + esd->decoderConfig->decoderSpecificInfo->dataLength)); memcpy(data, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength); memcpy(data + esd->decoderConfig->decoderSpecificInfo->dataLength, samp->data, samp->dataLength); AVI_write_frame(avi_out, data, samp->dataLength + esd->decoderConfig->decoderSpecificInfo->dataLength, 1); free(data); } else { AVI_write_frame(avi_out, samp->data, samp->dataLength, samp->IsRAP); } gf_isom_sample_del(&samp); while (frame_d) { AVI_write_frame(avi_out, dumdata, 1, 0); frame_d--; } gf_set_progress("AVI Export", i+1, count); if (dumper->flags & GF_EXPORT_DO_ABORT) break; } gf_odf_desc_del((GF_Descriptor *) esd); AVI_close(avi_out); return GF_OK;}GF_Err gf_media_export_nhml(GF_MediaExporter *dumper){ GF_ESD *esd; char szName[1000], szMedia[1000];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -