📄 media_export.c
字号:
sprintf(szName, "%s_%d%s", dumper->out_name, dumper->sample_num, szEXT); out = fopen(szName, "wb"); bs = gf_bs_from_file(out, GF_BITSTREAM_WRITE); if (is_mj2k) write_jp2_file(bs, samp->data, samp->dataLength, dsi, dsi_size); else gf_bs_write_data(bs, samp->data, samp->dataLength); gf_isom_sample_del(&samp); gf_bs_del(bs); fclose(out); if (dsi) free(dsi); return GF_OK; } 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; if (count>=1000) { sprintf(szName, "%s_%08d%s", dumper->out_name, i+1, szEXT); } else { sprintf(szName, "%s_%03d%s", dumper->out_name, i+1, szEXT); } out = fopen(szName, "wb"); bs = gf_bs_from_file(out, GF_BITSTREAM_WRITE); if (dsi) gf_bs_write_data(bs, dsi, dsi_size); if (is_mj2k) write_jp2_file(bs, samp->data, samp->dataLength, dsi, dsi_size); else gf_bs_write_data(bs, samp->data, samp->dataLength); gf_isom_sample_del(&samp); gf_set_progress("Media Export", i+1, count); gf_bs_del(bs); fclose(out); if (dumper->flags & GF_EXPORT_DO_ABORT) break; } if (dsi) free(dsi); return GF_OK;}static GF_Err gf_dump_to_vobsub(GF_MediaExporter *dumper, char *szName, u32 track, char *dsi, u32 dsiSize){ FILE *fidx, *fsub; u32 width, height, i, count, di; GF_ISOSample *samp; char lang[] = "\0\0\0\0"; /* Check decoder specific information (palette) size - should be 64 */ if (dsiSize != 64) { return gf_export_message(dumper, GF_CORRUPTED_DATA, "Invalid decoder specific info size - must be 64 but is %d", dsiSize); } /* Create an idx file */ fidx = gf_f64_open(szName, "w"); if (!fidx) { return gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName); } /* Create a sub file */ vobsub_trim_ext(szName); szName = strcat(szName, ".sub"); fsub = gf_f64_open(szName, "wb"); if (!fsub) { fclose(fidx); return gf_export_message(dumper, GF_IO_ERR, "Error opening %s for writing - check disk access & permissions", szName); } /* Retrieve original subpicture resolution */ gf_isom_get_track_layout_info(dumper->file, track, &width, &height, NULL, NULL, NULL); /* Write header */ fputs("# VobSub index file, v7 (do not modify this line!)\n#\n", fidx); /* Write original subpicture resolution */ fprintf(fidx, "size: %ux%u\n", width, height); /* Write palette */ fputs("palette:", fidx); for (i = 0; i < 16; i++) { s32 y, u, v, r, g, b; y = (s32)dsi[(i<<2)+1] - 0x10; u = (s32)dsi[(i<<2)+3] - 0x80; v = (s32)dsi[(i<<2)+2] - 0x80; r = (298 * y + 409 * v + 128) >> 8; g = (298 * y - 100 * u - 208 * v + 128) >> 8; b = (298 * y + 516 * u + 128) >> 8; if (i) fputc(',', fidx);#define CLIP(x) (((x) >= 0) ? (((x) < 256) ? (x) : 255) : 0) fprintf(fidx, " %02x%02x%02x", CLIP(r), CLIP(g), CLIP(b));#undef CLIP } fputc('\n', fidx); /* Write some other useful values */ fputs("# ON: displays only forced subtitles, OFF: shows everything\n", fidx); fputs("forced subs: OFF\n\n", fidx); /* Write current language index */ fputs("# Language index in use\nlangidx: 0\n", fidx); /* Write language header */ gf_isom_get_media_language(dumper->file, track, lang); fprintf(fidx, "id: %s, index: 0\n", vobsub_lang_id(lang)); /* Retrieve sample count */ count = gf_isom_get_sample_count(dumper->file, track); /* Process samples (skip first - because it is special) */ for (i = 2; i <= count; i++) { u64 dts; u32 hh, mm, ss, ms; samp = gf_isom_get_sample(dumper->file, track, i+1, &di); if (!samp) { break; } dts = samp->DTS / 90; ms = (u32)(dts % 1000); dts = dts / 1000; ss = (u32)(dts % 60); dts = dts / 60; mm = (u32)(dts % 60); hh = (u32)(dts / 60);#if defined(WIN32) && !defined(__GNUC__) fprintf(fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09lx\n", hh, mm, ss, ms, gf_f64_tell(fsub));#else fprintf(fidx, "timestamp: %02u:%02u:%02u:%03u, filepos: %09llx\n", hh, mm, ss, ms, gf_f64_tell(fsub));#endif if (vobsub_packetize_subpicture(fsub, samp->DTS, samp->data, samp->dataLength) != GF_OK) { gf_isom_sample_del(&samp); fclose(fsub); fclose(fidx); return gf_export_message(dumper, GF_IO_ERR, "Unable packetize subpicture into file %s\n", szName); } gf_isom_sample_del(&samp); gf_set_progress("VobSub Export", i + 1, count); if (dumper->flags & GF_EXPORT_DO_ABORT) { break; } } /* Delete sample if any */ if (samp) { gf_isom_sample_del(&samp); } fclose(fsub); fclose(fidx); return GF_OK;}/*QCP codec GUIDs*/static const char *QCP_QCELP_GUID_1 = "\x41\x6D\x7F\x5E\x15\xB1\xD0\x11\xBA\x91\x00\x80\x5F\xB4\xB9\x7E";static const char *QCP_EVRC_GUID = "\x8D\xD4\x89\xE6\x76\x90\xB5\x46\x91\xEF\x73\x6A\x51\x00\xCE\xB4";static const char *QCP_SMV_GUID = "\x75\x2B\x7C\x8D\x97\xA7\x46\xED\x98\x5E\xD5\x3C\x8C\xC7\x5F\x84";GF_Err gf_media_export_native(GF_MediaExporter *dumper){ GF_DecoderConfig *dcfg; GF_GenericSampleDescription *udesc; char szName[1000], szEXT[5], GUID[16]; FILE *out; u32 *qcp_rates; GF_AVCConfig *avccfg; GF_M4ADecSpecInfo a_cfg; GF_BitStream *bs; u32 track, i, di, count, m_type, m_stype, dsi_size, qcp_type; Bool is_ogg, has_qcp_pad, is_vobsub; u32 aac_type, is_aac; char *dsi; QCPRateTable rtable[8]; u32 rt_cnt; dsi_size = 0; dsi = NULL; avccfg = NULL; track = gf_isom_get_track_by_id(dumper->file, dumper->trackID); m_type = gf_isom_get_media_type(dumper->file, track); m_stype = gf_isom_get_media_subtype(dumper->file, track, 1); has_qcp_pad = 0; is_aac = aac_type = 0; qcp_type = 0; is_ogg = 0; is_vobsub = 0; udesc = NULL; dcfg = NULL; if ((m_stype==GF_ISOM_SUBTYPE_MPEG4) || (m_stype==GF_ISOM_SUBTYPE_MPEG4_CRYP)) dcfg = gf_isom_get_decoder_config(dumper->file, track, 1); strcpy(szName, dumper->out_name ? dumper->out_name : ""); if (dcfg) { switch (dcfg->streamType) { case GF_STREAM_VISUAL: switch (dcfg->objectTypeIndication) { case 0x20: dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; strcat(szName, ".cmp"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 Visual stream to cmp"); break; case 0x21: avccfg = gf_isom_avc_config_get(dumper->file, track, 1); strcat(szName, ".h264"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AVC-H264 stream to h264"); break; case 0x6A: strcat(szName, ".m1v"); gf_export_message(dumper, GF_OK, "Extracting MPEG-1 Visual stream to m1v"); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: strcat(szName, ".m2v"); gf_export_message(dumper, GF_OK, "Extracting MPEG-2 Visual stream to m2v"); break; case 0x6C: strcat(szName, ".jpg"); gf_export_message(dumper, GF_OK, "Extracting JPEG image"); break; case 0x6D: strcat(szName, ".png"); gf_export_message(dumper, GF_OK, "Extracting PNG image"); break; case GPAC_OGG_MEDIA_OTI: strcat(szName, ".ogg"); gf_export_message(dumper, GF_OK, "Extracting Ogg video"); is_ogg = 1; break; default: gf_odf_desc_del((GF_Descriptor *) dcfg); return gf_export_message(dumper, GF_NOT_SUPPORTED, "Unknown media in track ID %d - use NHNT instead", dumper->trackID); } break; case GF_STREAM_AUDIO: switch (dcfg->objectTypeIndication) { case 0x66: case 0x67: case 0x68: dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; strcat(szName, ".aac"); is_aac = 1; aac_type = dcfg->objectTypeIndication - 0x66; gf_export_message(dumper, GF_OK, "Extracting MPEG-2 AAC"); break; case 0x40: dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; is_aac = 2; strcat(szName, ".aac"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AAC"); break; case 0x69: case 0x6B: strcat(szName, ".mp3"); gf_export_message(dumper, GF_OK, "Extracting MPEG-1/2 Audio (MP3)"); break; case GPAC_OGG_MEDIA_OTI: strcat(szName, ".ogg"); is_ogg = 1; gf_export_message(dumper, GF_OK, "Extracting Ogg audio"); break; case 0xE1: strcat(szName, ".qcp"); qcp_type = 1; memcpy(GUID, QCP_QCELP_GUID_1, sizeof(char)*16); gf_export_message(dumper, GF_OK, "Extracting QCELP-13K (QCP file)"); break; case 0xA0: memcpy(GUID, QCP_EVRC_GUID, sizeof(char)*16); qcp_type = 3; if (dumper->flags & GF_EXPORT_PROBE_ONLY) dumper->flags |= GF_EXPORT_USE_QCP; break; case 0xA1: qcp_type = 2; memcpy(GUID, QCP_SMV_GUID, sizeof(char)*16); if (dumper->flags & GF_EXPORT_PROBE_ONLY) dumper->flags |= GF_EXPORT_USE_QCP; break; case 0xD1: if (dcfg->decoderSpecificInfo && (dcfg->decoderSpecificInfo->dataLength==8) && !strnicmp(dcfg->decoderSpecificInfo->data, "pvmm", 4)) { qcp_type = 3; memcpy(GUID, QCP_EVRC_GUID, sizeof(char)*16); if (dumper->flags & GF_EXPORT_PROBE_ONLY) dumper->flags |= GF_EXPORT_USE_QCP; break; } /*fall through*/ default: gf_odf_desc_del((GF_Descriptor *) dcfg); return gf_export_message(dumper, GF_NOT_SUPPORTED, "Unknown audio in track ID %d - use NHNT", dumper->trackID); } break; case GF_STREAM_ND_SUBPIC: switch (dcfg->objectTypeIndication) { case 0xe0: is_vobsub = 1; dsi = dcfg->decoderSpecificInfo->data; dcfg->decoderSpecificInfo->data = NULL; dsi_size = dcfg->decoderSpecificInfo->dataLength; strcat(szName, ".idx"); gf_export_message(dumper, GF_OK, "Extracting NeroDigital VobSub subpicture stream"); break; default: gf_odf_desc_del((GF_Descriptor *) dcfg); return gf_export_message(dumper, GF_NOT_SUPPORTED, "Unknown subpicture stream in track ID %d - use NHNT", dumper->trackID); } break; default: gf_odf_desc_del((GF_Descriptor *) dcfg); return gf_export_message(dumper, GF_NOT_SUPPORTED, "Cannot extract systems track ID %d in raw format - use NHNT", dumper->trackID); } gf_odf_desc_del((GF_Descriptor *) dcfg); } else { if (m_stype==GF_ISOM_SUBTYPE_3GP_AMR) { strcat(szName, ".amr"); gf_export_message(dumper, GF_OK, "Extracting AMR Audio"); } else if (m_stype==GF_ISOM_SUBTYPE_3GP_AMR_WB) { strcat(szName, ".awb"); gf_export_message(dumper, GF_OK, "Extracting AMR WideBand Audio"); } else if (m_stype==GF_ISOM_SUBTYPE_3GP_QCELP) { strcat(szName, ".qcp"); qcp_type = 1; memcpy(GUID, QCP_QCELP_GUID_1, sizeof(char)*16); gf_export_message(dumper, GF_OK, "Extracting QCELP-13K (QCP file)"); } else if (m_stype==GF_ISOM_SUBTYPE_3GP_EVRC) { qcp_type = 3; memcpy(GUID, QCP_EVRC_GUID, sizeof(char)*16); if (dumper->flags & GF_EXPORT_PROBE_ONLY) dumper->flags |= GF_EXPORT_USE_QCP; } else if (m_stype==GF_ISOM_SUBTYPE_3GP_SMV) { qcp_type = 2; memcpy(GUID, QCP_SMV_GUID, sizeof(char)*16); if (dumper->flags & GF_EXPORT_PROBE_ONLY) dumper->flags |= GF_EXPORT_USE_QCP; } else if (m_stype==GF_ISOM_SUBTYPE_3GP_H263) { gf_export_message(dumper, GF_OK, "Extracting H263 Video"); strcat(szName, ".263"); } else if (m_stype==GF_ISOM_SUBTYPE_AVC_H264) { avccfg = gf_isom_avc_config_get(dumper->file, track, 1); strcat(szName, ".h264"); gf_export_message(dumper, GF_OK, "Extracting MPEG-4 AVC-H264 stream to h264"); } else if (m_type==GF_ISOM_MEDIA_FLASH) { gf_export_message(dumper, GF_OK, "Extracting Macromedia Flash Movie"); strcat(szName, ".swf"); } else { strcat(szName, "."); strcat(szName, gf_4cc_to_str(m_stype)); udesc = gf_isom_get_generic_sample_description(dumper->file, track, 1); if (udesc) { dsi = udesc->extension_buf; udesc->extension_buf = NULL; dsi_size = udesc->extension_buf_size; } switch (m_type) { case GF_ISOM_MEDIA_VISUAL: gf_export_message(dumper, GF_OK, "Extracting \'%s\' Video - Compressor %s", szEXT, udesc ? udesc->compressor_name : "Unknown"); break; case GF_ISOM_MEDIA_AUDIO: gf_export_message(dumper, GF_OK, "Extracting \'%s\' Audio - Compressor %s", szEXT, udesc ? udesc->compressor_name : "Unknown"); break; default: gf_export_message(dumper, GF_OK, "Extracting \'%s\' Track (type '%s') - Compressor %s", szEXT, gf_4cc_to_str(m_type), udesc ? udesc->compressor_name : "Unknown"); break; } if (udesc) free(udesc); } } if (dumper->flags & GF_EXPORT_PROBE_ONLY) { if (dsi) free(dsi); if (avccfg) gf_odf_avc_cfg_del(avccfg); return GF_OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -