📄 media_import.c
字号:
} frame = import->esd->decoderConfig->decoderSpecificInfo->data + i + 4; frame = strchr(frame, 'p'); if (frame) { forced_packed = 1; frame[0] = 'n'; } break; } } if (import->flags & GF_IMPORT_FORCE_PACKED) forced_packed = 1; gf_isom_set_cts_packing(import->dest, track, 1); e = gf_isom_new_mpeg4_description(import->dest, track, import->esd, (import->flags & GF_IMPORT_USE_DATAREF) ? import->in_name: NULL, NULL, &di); if (e) goto exit; gf_isom_set_visual_info(import->dest, track, di, dsi.width, dsi.height); if (mpeg12) { gf_import_message(import, GF_OK, "MPEG-%d Video import - %d x %d @ %02.4f FPS", (dsi.VideoPL==0x6A) ? 1 : 2, dsi.width, dsi.height, FPS); } else { gf_import_message(import, GF_OK, "MPEG-4 Video import - %d x %d @ %02.4f FPS\nIndicated Profile: %s", dsi.width, dsi.height, FPS, gf_m4v_get_profile_name((u8) PL)); } gf_media_update_par(import->dest, track); has_cts_offset = 0; nb_samp = b_frames = ref_frame = 0; do_vfr = !(import->flags & GF_IMPORT_NO_FRAME_DROP); while (gf_bs_available(bs)) { u8 ftype; u32 tinc, frame_start; Bool is_coded; pos = gf_m4v_get_object_start(vparse); e = gf_m4v_parse_frame(vparse, dsi, &ftype, &tinc, &samp->dataLength, &frame_start, &is_coded); if (e==GF_EOS) e = GF_OK; if (e) goto exit; if (!is_coded) { nbNotCoded ++; /*if prev is B and we're parsing a packed bitstream discard n-vop*/ if (forced_packed && b_frames) { is_packed = 1; continue; } /*policy is to import at variable frame rate, skip*/ if (do_vfr) { is_vfr = 1; samp->DTS += dts_inc; continue; } /*policy is to keep non coded frame (constant frame rate), add*/ } samp->IsRAP = 0; if (ftype==2) { b_frames++; nbB++; /*adjust CTS*/ if (!has_cts_offset) { u32 i; for (i=0; i<gf_isom_get_sample_count(import->dest, track); i++) { gf_isom_modify_cts_offset(import->dest, track, i+1, dts_inc); } has_cts_offset = 1; } } else { if (ftype==0) { samp->IsRAP = 1; nbI++; } else { nbP++; } /*even if no out-of-order frames we MUST adjust CTS if cts_offset is present is */ if (ref_frame && has_cts_offset) gf_isom_modify_cts_offset(import->dest, track, ref_frame, (1+b_frames)*dts_inc); ref_frame = nb_samp+1; if (max_b<b_frames) max_b = b_frames; b_frames = 0; } if (!nb_samp) samp->DTS = 0; if (import->flags & GF_IMPORT_USE_DATAREF) { samp->data = NULL; e = gf_isom_add_sample_reference(import->dest, track, di, samp, frame_start); } else { if (samp->dataLength>max_size) { max_size = samp->dataLength; samp->data = (char*)realloc(samp->data, sizeof(char)*max_size); } gf_bs_seek(bs, frame_start); gf_bs_read_data(bs, samp->data, samp->dataLength); e = gf_isom_add_sample(import->dest, track, di, samp); } samp->DTS += dts_inc; nb_samp++; gf_set_progress("Importing M4V", done_size/1024, tot_size/1024); done_size += samp->dataLength; if (e) break; if (duration && (samp->DTS > duration)) break; if (import->flags & GF_IMPORT_DO_ABORT) break; } /*final flush*/ if (ref_frame && has_cts_offset) gf_isom_modify_cts_offset(import->dest, track, ref_frame, (1+b_frames)*dts_inc); gf_set_progress("Importing M4V", nb_samp, nb_samp); if (has_cts_offset) { gf_import_message(import, GF_OK, "Has B-Frames (%d max consecutive B-VOPs)", max_b); gf_isom_set_cts_packing(import->dest, track, 0); /*this is plain ugly but since some encoders (divx) don't use the video PL correctly we force the system video_pl to ASP@L5 since we have I, P, B in base layer*/ if (PL<=3) { PL = 0xF5; erase_pl = 1; gf_import_message(import, GF_OK, "WARNING: indicated profile doesn't include B-VOPs - forcing %s", gf_m4v_get_profile_name((u8) PL)); } gf_import_message(import, GF_OK, "Import results: %d VOPs (%d Is - %d Ps - %d Bs)", nb_samp, nbI, nbP, nbB); } else { /*no B-frames, remove CTS offsets*/ gf_isom_remove_cts_info(import->dest, track); gf_import_message(import, GF_OK, "Import results: %d VOPs (%d Is - %d Ps)", nb_samp, nbI, nbP); } if (erase_pl) { gf_m4v_rewrite_pl(&import->esd->decoderConfig->decoderSpecificInfo->data, &import->esd->decoderConfig->decoderSpecificInfo->dataLength, (u8) PL); gf_isom_change_mpeg4_description(import->dest, track, 1, import->esd); } MP4T_RecomputeBitRate(import->dest, track); if (is_vfr) { if (!nbB) { if (do_vfr) { gf_import_message(import, GF_OK, "import using Variable Frame Rate - Removed %d N-VOPs", nbNotCoded); } else { if (nbNotCoded) gf_import_message(import, GF_OK, "Stream has %d N-VOPs", nbNotCoded); } nbNotCoded = 0; } } if (nbNotCoded) gf_import_message(import, GF_OK, "Removed %d N-VOPs%s", nbNotCoded,is_packed ? " (Packed Bitstream)" : ""); gf_isom_set_pl_indication(import->dest, GF_ISOM_PL_VISUAL, (u8) PL);exit: if (samp) gf_isom_sample_del(&samp); if (destroy_esd) gf_odf_desc_del((GF_Descriptor *) import->esd); /*this destroys the bitstream as well*/ gf_m4v_parser_del(vparse); fclose(mdia); return e;}GF_Err gf_import_avi_video(GF_MediaImporter *import){ GF_Err e; Double FPS; FILE *test; GF_ISOSample *samp; u32 i, num_samples, timescale, size, max_size, samp_offset, track, di, PL, max_b, nb_f, ref_frame, b_frames; u32 nbI, nbP, nbB, nbDummy, nbNotCoded, dts_inc, cur_samp; Bool is_vfr, enable_vfr, erase_pl; GF_M4VDecSpecInfo dsi; GF_M4VParser *vparse; s32 key; u32 duration; Bool destroy_esd, is_packed, is_init, has_cts_offset; char *comp, *frame; avi_t *in; if (import->trackID>1) return GF_OK; test = fopen(import->in_name, "rb"); if (!test) return gf_import_message(import, GF_URL_ERROR, "Opening %s failed", import->in_name); fclose(test); in = AVI_open_input_file(import->in_name, 1); if (!in) return gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Unsupported avi file"); if (import->flags & GF_IMPORT_PROBE_ONLY) { char *comp; import->tk_info[0].track_num = 1; import->tk_info[0].type = GF_ISOM_MEDIA_VISUAL; import->tk_info[0].flags = GF_IMPORT_USE_DATAREF | GF_IMPORT_NO_FRAME_DROP | GF_IMPORT_OVERRIDE_FPS; import->tk_info[0].video_info.FPS = AVI_frame_rate(in); import->tk_info[0].video_info.width = AVI_video_width(in); import->tk_info[0].video_info.height = AVI_video_height(in); comp = AVI_video_compressor(in); import->tk_info[0].media_type = GF_4CC(comp[0], comp[1], comp[2], comp[3]); import->nb_tracks = 1; for (i=0; i<(u32) AVI_audio_tracks(in); i++) { import->tk_info[i+1].track_num = i+2; import->tk_info[i+1].type = GF_ISOM_MEDIA_AUDIO; import->tk_info[i+1].flags = GF_IMPORT_USE_DATAREF; import->tk_info[i+1].audio_info.sample_rate = AVI_audio_rate(in); import->tk_info[i+1].audio_info.nb_channels = AVI_audio_channels(in); import->nb_tracks ++; } AVI_close(in); return GF_OK; } destroy_esd = 0; frame = NULL; AVI_seek_start(in); erase_pl = 0; comp = AVI_video_compressor(in); if (!comp) { e = GF_NOT_SUPPORTED; goto exit; } /*these are/should be OK*/ if (!stricmp(comp, "DIVX") || !stricmp(comp, "DX50") /*DivX*/ || !stricmp(comp, "XVID") /*XviD*/ || !stricmp(comp, "3iv2") /*3ivX*/ || !stricmp(comp, "fvfw") /*ffmpeg*/ || !stricmp(comp, "NDIG") /*nero*/ || !stricmp(comp, "MP4V") /*!! not tested*/ || !stricmp(comp, "M4CC") /*Divio - not tested*/ || !stricmp(comp, "PVMM") /*PacketVideo - not tested*/ || !stricmp(comp, "SEDG") /*Samsung - not tested*/ || !stricmp(comp, "RMP4") /*Sigma - not tested*/ ) { e = GF_OK; } else if (!stricmp(comp, "DIV3") || !stricmp(comp, "DIV4")) { gf_import_message(import, GF_NOT_SUPPORTED, "Video format %s not compliant with MPEG-4 Visual - please recompress the file first", comp); e = GF_NOT_SUPPORTED; goto exit; } else if (!stricmp(comp, "H264") || !stricmp(comp, "X264")) { gf_import_message(import, GF_NOT_SUPPORTED, "H264/AVC Video format not supported in AVI - please extract to raw format first", comp); e = GF_NOT_SUPPORTED; goto exit; } else { gf_import_message(import, GF_NOT_SUPPORTED, "Video format %s not supported - recompress the file first", comp); e = GF_NOT_SUPPORTED; goto exit; } /*no auto frame-rate detection*/ if (import->video_fps == 10000.0) import->video_fps = 25.0; FPS = AVI_frame_rate(in); if (import->video_fps) FPS = (Double) import->video_fps; get_video_timing(FPS, ×cale, &dts_inc); duration = (u32) (import->duration*FPS); e = GF_OK; max_size = 0; samp_offset = 0; frame = NULL; num_samples = AVI_video_frames(in); samp = gf_isom_sample_new(); PL = 0; track = 0; is_vfr = 0; is_packed = 0; nbDummy = nbNotCoded = nbI = nbP = nbB = max_b = 0; enable_vfr = 0; has_cts_offset = 0; cur_samp = b_frames = ref_frame = 0; is_init = 0; for (i=0; i<num_samples; i++) { size = AVI_frame_size(in, i); if (!size) { AVI_read_frame(in, NULL, &key); continue; } if (size > max_size) { frame = (char*)realloc(frame, sizeof(char) * size); max_size = size; } AVI_read_frame(in, frame, &key); /*get DSI*/ if (!is_init) { is_init = 1; vparse = gf_m4v_parser_new(frame, size, 0); e = gf_m4v_parse_config(vparse, &dsi); PL = dsi.VideoPL; if (!PL) { PL = 0x01; erase_pl = 1; } samp_offset = gf_m4v_get_object_start(vparse); gf_m4v_parser_del(vparse); if (e) { gf_import_message(import, e, "Cannot import decoder config in first frame"); goto exit; } if (!import->esd) { import->esd = gf_odf_desc_esd_new(0); destroy_esd = 1; } track = gf_isom_new_track(import->dest, import->esd->ESID, GF_ISOM_MEDIA_VISUAL, timescale); if (!track) { e = gf_isom_last_error(import->dest); goto exit; } gf_isom_set_track_enabled(import->dest, track, 1); if (!import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track); import->final_trackID = gf_isom_get_track_id(import->dest, track); if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); import->esd->slConfig->timestampResolution = timescale; if (!import->esd->decoderConfig) import->esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); if (import->esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) import->esd->decoderConfig->decoderSpecificInfo); import->esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); import->esd->decoderConfig->streamType = GF_STREAM_VISUAL; import->esd->decoderConfig->objectTypeIndication = 0x20; import->esd->decoderConfig->decoderSpecificInfo->data = (char *) malloc(sizeof(char) * samp_offset); memcpy(import->esd->decoderConfig->decoderSpecificInfo->data, frame, sizeof(char) * samp_offset); import->esd->decoderConfig->decoderSpecificInfo->dataLength = samp_offset; gf_isom_set_cts_packing(import->dest, track, 1); /*remove packed flag if any (VOSH user data)*/ while (1) { char *divx_mark; while ((i+3<samp_offset) && ((frame[i]!=0) || (frame[i+1]!=0) || (frame[i+2]!=1))) i++; if (i+4>=samp_offset) break; if (strncmp(frame+i+4, "DivX", 4)) { i += 4; continue; } divx_mark = import->esd->decoderConfig->decoderSpecificInfo->data + i + 4; divx_mark = strchr(divx_mark, 'p'); if (divx_mark) divx_mark[0] = 'n'; break; } i = 0; e = gf_isom_new_mpeg4_description(import->dest, track, import->esd, (import->flags & GF_IMPORT_USE_DATAREF) ? import->in_name: NULL, NULL, &di); if (e) goto exit; gf_isom_set_visual_info(import->dest, track, di, dsi.width, dsi.height); gf_import_message(import, GF_OK, "AVI %s video import - %d x %d @ %02.4f FPS - %d Frames\nIndicated Profile: %s", comp, dsi.width, dsi.height, FPS, num_samples, gf_m4v_get_profile_name((u8) PL)); gf_media_update_par(import->dest, track); } if (size > samp_offset) { u8 ftype; u32 tinc, framesize, frame_start; u64 file_offset; Bool is_coded; size -= samp_offset; file_offset = (u64) AVI_get_video_position(in, i); vparse = gf_m4v_parser_new(frame + samp_offset, size, 0); samp->dataLength = 0; /*removing padding frames*/ if (size<4) { nbDummy ++; size = 0; } nb_f=0; while (size) { GF_Err e = gf_m4v_parse_frame(vparse, dsi, &ftype, &tinc, &framesize, &frame_start, &is_coded); if (e<0) goto exit; if (!is_coded) { if (!gf_m4v_is_valid_object_type(vparse)) gf_import_message(import, GF_OK, "WARNING: AVI frame %d doesn't look like MPEG-4 Visual", i+1); nbNotCoded ++; if (!is_packed) { is_vfr = 1; /*policy is to import at constant frame rate from AVI*/ if (import->flags & GF_IMPORT_NO_FRAME_DROP) goto proceed; /*policy is to import at variable frame rate from AVI*/ samp->DTS += dts_inc; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -