📄 swf_parse.c
字号:
SWFSound *snd; GF_SAFEALLOC(snd , SWFSound); snd->ID = swf_get_16(read); snd->format = swf_read_int(read, 4); snd->sound_rate = swf_read_int(read, 2); snd->bits_per_sample = swf_read_int(read, 1) ? 16 : 8; snd->stereo = swf_read_int(read, 1); snd->sample_count = swf_get_32(read); switch (snd->format) { /*raw PCM*/ case 0: swf_report(read, GF_NOT_SUPPORTED, "Raw PCM Audio not supported"); free(snd); break; /*ADPCM*/ case 1: swf_report(read, GF_NOT_SUPPORTED, "AD-PCM Audio not supported"); free(snd); break; /*MP3*/ case 2: { unsigned char bytes[4]; char szName[1024]; u32 hdr, alloc_size, size, tot_size; char *frame; sprintf(szName, "swf_sound_%d.mp3", snd->ID); if (read->localPath) { snd->szFileName = (char*)malloc(sizeof(char)*GF_MAX_PATH); strcpy(snd->szFileName, read->localPath); strcat(snd->szFileName, szName); } else { snd->szFileName = strdup(szName); } snd->output = fopen(snd->szFileName, "wb"); alloc_size = 1; frame = (char*)malloc(sizeof(char)); snd->frame_delay_ms = swf_get_16(read); snd->frame_delay_ms = 0; tot_size = 9; /*parse all frames*/ while (1) { bytes[0] = swf_read_int(read, 8); bytes[1] = swf_read_int(read, 8); bytes[2] = swf_read_int(read, 8); bytes[3] = swf_read_int(read, 8); hdr = GF_4CC(bytes[0], bytes[1], bytes[2], bytes[3]); size = gf_mp3_frame_size(hdr); if (alloc_size<size-4) { frame = (char*)realloc(frame, sizeof(char)*(size-4)); alloc_size = size-4; } /*watchout for truncated framesif */ if (tot_size + size >= read->size) size = read->size - tot_size; swf_read_data(read, frame, size-4); fwrite(bytes, sizeof(char)*4, 1, snd->output); fwrite(frame, sizeof(char)*(size-4), 1, snd->output); if (tot_size + size >= read->size) break; tot_size += size; } free(frame); return gf_list_add(read->sounds, snd); } case 3: swf_report(read, GF_NOT_SUPPORTED, "Unrecognized sound format"); free(snd); break; } return GF_OK;}typedef struct{ u32 sync_flags; u32 in_point, out_point; u32 nb_loops;} SoundInfo; SoundInfo swf_skip_soundinfo(SWFReader *read){ SoundInfo si; u32 sync_flags = swf_read_int(read, 4); Bool has_env = swf_read_int(read, 1); Bool has_loops = swf_read_int(read, 1); Bool has_out_pt = swf_read_int(read, 1); Bool has_in_pt = swf_read_int(read, 1); memset(&si, 0, sizeof(SoundInfo)); si.sync_flags = sync_flags; if (has_in_pt) si.in_point = swf_get_32(read); if (has_out_pt) si.out_point = swf_get_32(read); if (has_loops) si.nb_loops = swf_get_16(read); /*we ignore the envelope*/ if (has_env) { u32 i; u32 nb_ctrl = swf_read_int(read, 8); for (i=0; i<nb_ctrl; i++) { swf_read_int(read, 32); /*mark44*/ swf_read_int(read, 16); /*l0*/ swf_read_int(read, 16); /*l1*/ } } return si;}SWFSound *sndswf_get_sound(SWFReader *read, u32 ID){ u32 i; SWFSound *snd; i=0; while ((snd = (SWFSound *)gf_list_enum(read->sounds, &i))) { if (snd->ID==ID) return snd; } return NULL;}GF_Err swf_setup_sound(SWFReader *read, SWFSound *snd){ GF_Err e; GF_ObjectDescriptor *od; GF_ESD *esd; GF_MuxInfo *mux; GF_Node *n, *par; GF_FieldInfo info; u32 ID; char szDEF[100]; e = swf_init_od(read); if (e) return e; /*create audio object*/ od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG); if (!od) return GF_OUT_OF_MEM; od->objectDescriptorID = swf_get_od_id(read); esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG); if (!esd) return GF_OUT_OF_MEM; esd->ESID = swf_get_es_id(read); if (snd->ID) { /*sound runs on its own timeline*/ esd->OCRESID = esd->ESID; } else { /*soundstream runs on movie/sprite timeline*/ esd->OCRESID = read->bifs_es->ESID; } gf_list_add(od->ESDescriptors, esd); /*setup mux info*/ mux = (GF_MuxInfo*)gf_odf_desc_new(GF_ODF_MUXINFO_TAG); mux->file_name = strdup(snd->szFileName); mux->startTime = snd->frame_delay_ms; /*MP3 in, destroy file once done*/ if (snd->format==2) mux->delete_file = 1; gf_list_add(esd->extensionDescriptors, mux); /*by default insert OD at begining*/ e = swf_insert_od(read, 0, od); if (e) { gf_odf_desc_del((GF_Descriptor *) od); return e; } /*create sound & audio clip*/ n = SWF_NewNode(read, TAG_MPEG4_Sound2D); gf_node_insert_child(read->root, n, 0); gf_node_register(n, read->root); par = n; n = SWF_NewNode(read, TAG_MPEG4_AudioClip); /*soundStream doesn't have ID and doesn't need to be accessed*/ if (snd->ID) { sprintf(szDEF, "Sound%d", snd->ID); read->load->ctx->max_node_id++; ID = read->load->ctx->max_node_id; gf_node_set_id(n, ID, szDEF); } ((M_Sound2D *)par)->source = n; gf_node_register(n, par); /*assign URL*/ gf_node_get_field_by_name(n, "url", &info); gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1); ((MFURL *)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID; snd->is_setup = 1; return GF_OK;}GF_Err swf_start_sound(SWFReader *read){ char szDEF[100]; GF_Command *com; GF_FieldInfo info; GF_Node *sound2D; GF_CommandField *f; SWFSound *snd; u32 ID = swf_get_16(read); SoundInfo si = swf_skip_soundinfo(read); snd = sndswf_get_sound(read, ID); if (!snd) { swf_report(read, GF_BAD_PARAM, "Cannot find sound with ID %d", ID); return GF_OK; } if (!snd->is_setup) { GF_Err e = swf_setup_sound(read, snd); if (e) return e; } sprintf(szDEF, "Sound%d", snd->ID); sound2D = gf_sg_find_node_by_name(read->load->scene_graph, szDEF); /*check flags*/ if (si.sync_flags & 0x2) { /*need a STOP*/ com = gf_sg_command_new(read->load->scene_graph, GF_SG_FIELD_REPLACE); com->node = sound2D; gf_node_register(com->node, NULL); gf_node_get_field_by_name(sound2D, "stopTime", &info); f = gf_sg_command_field_new(com); f->field_ptr = gf_sg_vrml_field_pointer_new(GF_SG_VRML_SFTIME); f->fieldType = GF_SG_VRML_SFTIME; f->fieldIndex = info.fieldIndex; /*replace by "now"*/ *(SFTime *)f->field_ptr = ((Double)(s64) read->bifs_au->timing) / read->bifs_es->timeScale; *(SFTime *)f->field_ptr = 0; gf_list_add(read->bifs_au->commands, com); } com = gf_sg_command_new(read->load->scene_graph, GF_SG_FIELD_REPLACE); com->node = sound2D; gf_node_register(com->node, NULL); gf_node_get_field_by_name(sound2D, "startTime", &info); f = gf_sg_command_field_new(com); f->field_ptr = gf_sg_vrml_field_pointer_new(GF_SG_VRML_SFTIME); f->fieldType = GF_SG_VRML_SFTIME; f->fieldIndex = info.fieldIndex; /*replace by "now"*/ *(SFTime *)f->field_ptr = ((Double)(s64) read->bifs_au->timing) / read->bifs_es->timeScale; *(SFTime *)f->field_ptr = 0; gf_list_add(read->bifs_au->commands, com); return GF_OK;}GF_Err swf_soundstream_hdr(SWFReader *read){ u8 rec_mix; u32 samplesperframe; SWFSound *snd; if (read->sound_stream) { swf_report(read, GF_BAD_PARAM, "More than one sound stream for current timeline!!"); return swf_func_skip(read); } GF_SAFEALLOC(snd, SWFSound); rec_mix = swf_read_int(read, 8); /*0: uncompressed, 1: ADPCM, 2: MP3*/ snd->format = swf_read_int(read, 4); /*0: 5.5k, 1: 11k, 2: 2: 22k, 3: 44k*/ snd->sound_rate = swf_read_int(read, 2); /*0: 8 bit, 1: 16 bit*/ snd->bits_per_sample = swf_read_int(read, 1) ? 16 : 8; /*0: mono, 8 1: stereo*/ snd->stereo = swf_read_int(read, 1); /*samplesperframe hint*/ samplesperframe = swf_read_int(read, 16); switch (snd->format) { /*raw PCM*/ case 0: swf_report(read, GF_NOT_SUPPORTED, "Raw PCM Audio not supported"); free(snd); break; /*ADPCM*/ case 1: swf_report(read, GF_NOT_SUPPORTED, "AD-PCM Audio not supported"); free(snd); break; /*MP3*/ case 2: read->sound_stream = snd; break; case 3: swf_report(read, GF_NOT_SUPPORTED, "Unrecognized sound format"); free(snd); break; } return GF_OK;}GF_Err swf_soundstream_block(SWFReader *read){ unsigned char bytes[4]; u32 hdr, alloc_size, size, tot_size, samplesPerFrame, delay; char *frame; /*note we're doing only MP3*/ if (!read->sound_stream) return swf_func_skip(read); samplesPerFrame = swf_get_16(read); delay = swf_get_16(read); if (!read->sound_stream->is_setup) { if (!read->sound_stream->szFileName) { char szName[1024]; sprintf(szName, "swf_soundstream_%d.mp3", (u32) read->sound_stream); if (read->localPath) { read->sound_stream->szFileName = (char*)malloc(sizeof(char)*GF_MAX_PATH); strcpy(read->sound_stream->szFileName, read->localPath); strcat(read->sound_stream->szFileName, szName); } else { read->sound_stream->szFileName = strdup(szName); } read->sound_stream->output = fopen(read->sound_stream->szFileName, "wb"); } /*error at setup*/ if (!read->sound_stream->output) return swf_func_skip(read); /*store TS of first AU*/ read->sound_stream->frame_delay_ms = read->current_frame*1000; read->sound_stream->frame_delay_ms /= read->frame_rate; read->sound_stream->frame_delay_ms = delay; swf_setup_sound(read, read->sound_stream); } if (!samplesPerFrame) return GF_OK; alloc_size = 1; frame = (char*)malloc(sizeof(char)); tot_size = 4; /*parse all frames*/ while (1) { bytes[0] = swf_read_int(read, 8); bytes[1] = swf_read_int(read, 8); bytes[2] = swf_read_int(read, 8); bytes[3] = swf_read_int(read, 8); hdr = GF_4CC(bytes[0], bytes[1], bytes[2], bytes[3]); size = gf_mp3_frame_size(hdr); if (alloc_size<size-4) { frame = (char*)realloc(frame, sizeof(char)*(size-4)); alloc_size = size-4; } /*watchout for truncated framesif */ if (tot_size + size >= read->size) size = read->size - tot_size; swf_read_data(read, frame, size-4); fwrite(bytes, sizeof(char)*4, 1, read->sound_stream->output); fwrite(frame, sizeof(char)*(size-4), 1, read->sound_stream->output); if (tot_size + size >= read->size) break; tot_size += size; } free(frame); return GF_OK;}GF_Err swf_process_tag(SWFReader *read){ switch (read->tag) { case SWF_END: return GF_OK; /*void*/ case SWF_PROTECT: return GF_OK; case SWF_SETBACKGROUNDCOLOR: return swf_set_backcol(read); case SWF_DEFINESHAPE: return swf_def_shape(read, 0); case SWF_DEFINESHAPE2: return swf_def_shape(read, 1); case SWF_DEFINESHAPE3: return swf_def_shape(read, 2); case SWF_PLACEOBJECT: return swf_place_obj(read, 0); case SWF_PLACEOBJECT2: return swf_place_obj(read, 1); case SWF_SHOWFRAME: return swf_show_frame(read); case SWF_REMOVEOBJECT: return swf_remove_obj(read, 0); case SWF_REMOVEOBJECT2: return swf_remove_obj(read, 1); case SWF_DEFINEFONT: return swf_def_font(read, 0); case SWF_DEFINEFONT2: return swf_def_font(read, 1); case SWF_DEFINEFONTINFO: return swf_def_font_info(read); case SWF_DEFINETEXT: return swf_def_text(read, 0); case SWF_DEFINETEXT2: return swf_def_text(read, 1); case SWF_DEFINESPRITE: return swf_def_sprite(read); /*no revision needed*/ case SWF_SOUNDSTREAMHEAD: case SWF_SOUNDSTREAMHEAD2: return swf_soundstream_hdr(read); case SWF_DEFINESOUND: return swf_def_sound(read); case SWF_STARTSOUND: return swf_start_sound(read); case SWF_SOUNDSTREAMBLOCK: return swf_soundstream_block(read); case SWF_DEFINEBUTTON: return swf_def_button(read, 0); case SWF_DEFINEBUTTON2: return swf_def_button(read, 1); case SWF_DEFINEBUTTONSOUND: case SWF_DOACTION: read->has_interact = 1; swf_report(read, GF_OK, "skipping tag %s", swf_get_tag(read->tag) ); return swf_func_skip(read);/* case SWF_DEFINEBITSJPEG: return swf_def_bits_jpeg(read); case SWF_JPEGTABLES: return swf_def_hdr_jpeg(read); case SWF_SOUNDSTREAMHEAD: return swf_sound_hdr(read); case SWF_SOUNDSTREAMBLOCK: return swf_sound_block(read); case SWF_DEFINEBITSLOSSLESS: return swf_def_bits_lossless(read); case SWF_DEFINEBITSJPEG2: return swf_def_bits_jpegV2(read); case SWF_DEFINEBITSJPEG3: return swf_def_bits_jpegV3(read); case SWF_DEFINEBITSLOSSLESS2: return swf_def_bits_losslessV2(read); case SWF_FRAMELABEL: return swf_def_frame_label(read);*/ default: return swf_unknown_tag(read); }}GF_Err SWF_ParseTag(SWFReader *read){ GF_Err e; s32 diff; u16 hdr; u32 pos; hdr = swf_get_16(read); read->tag = hdr>>6; read->size = hdr & 0x3f; if (read->size == 0x3f) { swf_align(read); read->size = swf_get_32(read); } pos = swf_get_file_pos(read); diff = pos + read->size; gf_set_progress("SWF Parsing", pos, read->length); e = swf_process_tag(read); swf_align(read); diff -= swf_get_file_pos(read); if (diff<0) { swf_report(read, GF_IO_ERR, "tag over-read of %d bytes (size %d)", -1*diff, read->size); return GF_IO_ERR; } else { swf_read_int(read, diff*8); } if (!e && !read->tag) return GF_EOS; if (read->ioerr) { swf_report(read, GF_IO_ERR, "bitstream IO err (tag size %d)", read->size); return read->ioerr; } return e;}void swf_report(SWFReader *read, GF_Err e, char *format, ...){#ifndef GPAC_DISABLE_LOG if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) { char szMsg[2048]; va_list args; va_start(args, format); vsprintf(szMsg, format, args); va_end(args); GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[SWF Parsing] %s (frame %d)\n", szMsg, read->current_frame+1) ); }#endif}const char *swf_get_tag(u32 tag){ switch (tag) { case SWF_END: return "End"; case SWF_SHOWFRAME: return "ShowFrame"; case SWF_DEFINESHAPE: return "DefineShape"; case SWF_FREECHARACTER: return "FreeCharacter"; case SWF_PLACEOBJECT: return "PlaceObject"; case SWF_REMOVEOBJECT: return "RemoveObject"; case SWF_DEFINEBITSJPEG: return "DefineBitsJPEG"; case SWF_DEFINEBUTTON: return "DefineButton"; case SWF_JPEGTABLES: return "JPEGTables"; case SWF_SETBACKGROUNDCOLOR: return "SetBackgroundColor"; case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -