📄 asf.c
字号:
break; case ASF_FILE_TRANSFER_MEDIA_STREAM: /* File transfer media stream... I don't know what the heck this is.*/ display(MSDL_VER,"File transfer stream detected, but ignore this.\n"); break; } } a_rates = xmalloc(streams->n_audio * sizeof(int)); v_rates = xmalloc(streams->n_video * sizeof(int)); pos = find_asf_guid(header,start,asf_stream_group_guid,asf_header_size); if(pos >= 0) { /* stream bitrate proterties object */ int stream_count = 0; uint8_t *ptr = (uint8_t *)header + pos; display(MSDL_VER,"stream bitrate properties object\n"); stream_count = get16_le(ptr); /* little endian. */ ptr += sizeof(uint16_t); if(ptr > header + asf_header_size) goto failed; display(MSDL_VER,"stream count = [0x%x] [%u]\n",stream_count,stream_count); display(MSDL_VER,"audio streams: %d, video streams: %d\n", streams->n_audio,streams->n_video); for(i = 0; i < stream_count; i++) { uint32_t rate = 0; int id = 0; int j = 0; id = get16_le(ptr); ptr += sizeof(uint16_t); if(ptr > header + asf_header_size) goto failed; rate = get32_le(ptr); ptr += sizeof(uint32_t); if(ptr > header + asf_header_size) goto failed; display(MSDL_VER, "stream_id = [0x%x] [%u]\n" "max bitrate = [0x%x] [%u]\n", id,id,rate,rate); for(j = 0; j < streams->n_audio; j++) { if(id == streams->audio_streams[j]) { display(MSDL_VER,"is audio stream\n"); a_rates[j] = rate; break; } } for(j = 0; j < streams->n_video; j++) { if(id == streams->video_streams[j]) { display(MSDL_VER,"is video stream\n"); v_rates[j] = rate; break; } } } } /* just to make sure bw is not Zero! */ if(bw == 0) { bw = INT_MAX_BANDWIDTH; } if(streams->n_audio) { /* find lowest-bitrate audio stream */ a_rate = a_rates[0]; a_idx = 0; for(i = 0; i < streams->n_audio; i++) { if(a_rates[i] < a_rate) { a_rate = a_rates[i]; a_idx = i; } } if(max_idx(streams->n_video,v_rates,bw - a_rate) < 0) { /* both audio and video are not possible, try video only next */ a_idx = -1; a_rate = 0; } } /* find best video stream */ v_idx = max_idx(streams->n_video,v_rates,bw - a_rate); if(v_idx >= 0) { v_rate = v_rates[v_idx]; } /* find best auido stream */ a_idx = max_idx(streams->n_audio,a_rates,bw - v_rate); free(v_rates); v_rates = NULL; free(a_rates); a_rates = NULL; if(a_idx < 0 && v_idx < 0) { display(MSDL_ERR,"bandwidth too low ... cannot get streams."); return -1; } if(a_idx >= 0) { streams->audio_id = streams->audio_streams[a_idx]; } else if(streams->n_audio) { display(MSDL_ERR,"Bandwidth too too small so deselected audio....sad.\n"); } if(v_idx >= 0) { streams->video_id = streams->video_streams[v_idx]; } else if(streams->n_video) { display(MSDL_ERR,"Bandwidth too too small so deselected video....sad.\n"); } return 1; failed: free(v_rates); free(a_rates); return -1;}/* * get send_time of ASF data packet * return value: 1 */int asf_data_packet_get_send_time(uint8_t *packet,uint32_t *send_time){ struct asf_data_packet_header_t adph; asf_parse_data_packet_header(packet,&adph); *send_time = adph.ppi.send_time; return 1;}/* * get info for resuming * @send_time : last packet npt (out) * @seek_offset: last packet offset (out) * return value: 1 ... success * -1 ... failure */int asf_get_npt_of_last_packet(char *local_filename,uint32_t *send_time,uint64_t *seek_offset){ FILE *lfp = NULL; uint8_t *asf_header_buffer = NULL; uint32_t header_buffer_size = ASF_HEADER_READ_AT_ONCE; uint32_t header_buffer_filled = 0; uint8_t *last_packet_buffer = NULL; size_t ret = 0; uint64_t asf_header_object_size = 0; uint64_t asf_packet_start_offset = 0; struct asf_file_header_t *fileh = NULL; int packet_size = 0; uint64_t file_size = 0; uint64_t last_data_packet_offset = 0; uint32_t last_send_time = 0; enum { ASF_DATA_OBJECT_HEADER_SIZE = 16 + 8 + 16 + 8 + 2, }; if((lfp = fopen(local_filename,"rb")) == NULL) { display(MSDL_ERR, "resume \"%s\" : cannot open file for resume\n",local_filename); goto failed; } asf_header_buffer = (uint8_t *)xmalloc(header_buffer_size); /* read */ ret = fread(asf_header_buffer,sizeof(uint8_t),header_buffer_size,lfp); if(!ret) { if(ferror(lfp)) { display(MSDL_ERR,"resume \"%s\": asf_header_buffer_read_failed\n"); goto failed; } } header_buffer_filled = ret; if(ret < ASF_HEADER_READ_AT_ONCE) { if(ferror(lfp)) { display(MSDL_ERR,"resume \"%s\": cannot read file \n",local_filename); } else { display(MSDL_ERR,"resume \"%s\": too small for resume\n",local_filename); } /* couldn't read, or just only very small amount of data in file*/ goto failed; } if(memcmp(asf_header_buffer,asf_header_object_guid,ASF_GUID_LENGTH)) { /* not the asf file */ display(MSDL_ERR,"resume \"%s\": not an asf file\n",local_filename); goto failed; } asf_header_object_size = get64_le(asf_header_buffer + ASF_GUID_LENGTH); /* fill header buffer */ if(asf_header_object_size + ASF_DATA_OBJECT_HEADER_SIZE > header_buffer_size) { header_buffer_size = asf_header_object_size + ASF_DATA_OBJECT_HEADER_SIZE; asf_header_buffer = (uint8_t *)xrealloc(asf_header_buffer,header_buffer_size); ret = fread(asf_header_buffer + header_buffer_filled, sizeof(uint8_t), header_buffer_size - header_buffer_filled, lfp); if(!ret) { if(ferror(lfp)) { display(MSDL_ERR,"resume \"%s\": asf_header_buffer_read_failed\n"); goto failed; } } } /* make sure all file properties object is read in memory */ fileh = new_asf_file_header_t(); packet_size = asf_get_file_property(asf_header_buffer, asf_header_object_size, fileh); if(packet_size < 0) { display(MSDL_ERR,"resume \"%s\": asf file header error\n",local_filename); goto failed; } if(memcmp(asf_header_buffer + asf_header_object_size,asf_data_object_guid,ASF_GUID_LENGTH)) { display(MSDL_ERR,"resume \"%s\": could not find ASF_data_object\n",local_filename); goto failed; } asf_packet_start_offset = asf_header_object_size + ASF_DATA_OBJECT_HEADER_SIZE; ret = get_filesize(local_filename,&file_size); if(ret < 0) { /* stat() failed */ goto failed; } if(file_size < (packet_size * 2)) { /* not likely, but this will cause problem below */ display(MSDL_ERR,"resume \"%s\": not enough data for getting resume info\n",local_filename); goto failed; } last_data_packet_offset = file_size - ((file_size - asf_packet_start_offset) % packet_size) - packet_size; display(MSDL_DBG, "resume \"%s\": last asf data packet is at 0x%x\n",local_filename, last_data_packet_offset); last_packet_buffer = xmalloc(packet_size); fseek(lfp,last_data_packet_offset,SEEK_SET); ret = fread(last_packet_buffer,sizeof(uint8_t),packet_size,lfp); if(ret < packet_size) { display(MSDL_ERR,"resume \"%s\": coulnd't read last packet\n",local_filename); goto failed; } asf_data_packet_get_send_time(last_packet_buffer,&last_send_time); if(lfp) fclose(lfp); if(asf_header_buffer) free(asf_header_buffer); if(last_packet_buffer) free(last_packet_buffer); if(fileh) free_asf_file_header_t(fileh); display(MSDL_NOR, "resume \"%s\": try to resume from %ds\n",local_filename,last_send_time / 1000); *send_time = last_send_time; *seek_offset = last_data_packet_offset; return 1; failed: if(lfp) fclose(lfp); if(asf_header_buffer) free(asf_header_buffer); if(last_packet_buffer) free(last_packet_buffer); if(fileh) free_asf_file_header_t(fileh); display(MSDL_ERR,"just get file from beginning.\n"); *send_time = 0; *seek_offset = 0; return -1;}int asf_parse_data_packet_header(uint8_t *packet,struct asf_data_packet_header_t *adph){ uint8_t ecd_flags = packet[0]; uint8_t length_type_flags = 0; uint8_t property_flags = 0; int ppi_offset = 0; int next_offset = 0; /* length type dependent stuff */ const int length_type_table[4] = {0,1,2,4}; adph->ecd.error_correction_data_length = ecd_flags & 0x0f; adph->ecd.opaque_data_present = (ecd_flags >> 4) & 0x01; adph->ecd.error_correction_length_type = (ecd_flags >> 5) & 0x03; adph->ecd.error_correction_present = (ecd_flags >> 7) & 0x01; if(adph->ecd.error_correction_present) { ppi_offset = 1 + adph->ecd.error_correction_data_length; } else { ppi_offset = 1; } length_type_flags = packet[ppi_offset]; property_flags = packet[ppi_offset + 1]; adph->ppi.multiple_payloads_present = length_type_flags & 0x01; adph->ppi.sequence_type = (length_type_flags >> 1) & 0x03; adph->ppi.padding_length_type = (length_type_flags >> 3) & 0x03; adph->ppi.packet_length_type = (length_type_flags >> 5) & 0x03; adph->ppi.error_correction_present = (length_type_flags >> 7) & 0x01; adph->ppi.replicated_data_length_type = property_flags & 0x03; adph->ppi.offset_into_media_object_length_type = (property_flags >> 2) & 0x03; adph->ppi.media_object_number_length_type = (property_flags >> 4) & 0x03; adph->ppi.stream_number_length_type = (property_flags >> 6) & 0x03; next_offset = ppi_offset + 2; /* packet length */ adph->ppi.packet_length = getnb_le(packet + next_offset,length_type_table[adph->ppi.packet_length_type]); next_offset += length_type_table[adph->ppi.packet_length_type]; /* sequence */ adph->ppi.sequence = getnb_le(packet + next_offset,length_type_table[adph->ppi.sequence_type]); next_offset += length_type_table[adph->ppi.sequence_type]; /* padding length */ adph->ppi.padding_length = getnb_le(packet + next_offset,length_type_table[adph->ppi.padding_length_type]); next_offset += length_type_table[adph->ppi.padding_length_type]; adph->ppi.send_time = get32_le(packet + next_offset); next_offset += sizeof(uint32_t); adph->ppi.duration = get16_le(packet + next_offset); next_offset += sizeof(uint16_t); return next_offset;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -