📄 vorbis.c
字号:
track_map->track, track_map->current_position); else quicktime_chunk_of_sample(&chunk_sample, &(track_map->current_chunk), track_map->track, track_map->current_position); if(track_map->current_chunk >= file->atracks[track].track->mdia.minf.stbl.stco.total_entries) { return 0; } /* Reset everything */ vorbis_dsp_clear(&codec->dec_vd); vorbis_block_clear(&codec->dec_vb); ogg_stream_clear(&codec->dec_os); ogg_sync_reset(&codec->dec_oy); codec->stream_initialized = 0; /* Initialize again */ ogg_sync_init(&codec->dec_oy); // ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og)); vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi); vorbis_block_init(&codec->dec_vd, &codec->dec_vb); if(!next_page(file, track)) return 0; /* Reset sample buffer */ codec->sample_buffer_start = chunk_sample; codec->sample_buffer_end = chunk_sample; /* Decode frames until we have enough */ while(track_map->current_position + samples > codec->sample_buffer_end) { if(!decode_frame(file, track)) break; } } /* Flush unneeded samples */ if(track_map->current_position > codec->sample_buffer_start) { samples_to_skip = track_map->current_position - codec->sample_buffer_start; samples_to_move = codec->sample_buffer_end - track_map->current_position; if(samples_to_move > 0) { for(i = 0; i < track_map->channels; i++) { memmove(codec->sample_buffer[i], &(codec->sample_buffer[i][samples_to_skip]), samples_to_move * sizeof(float)); } } codec->sample_buffer_start = track_map->current_position; if(samples_to_move > 0) codec->sample_buffer_end = codec->sample_buffer_start + samples_to_move; else codec->sample_buffer_end = codec->sample_buffer_start; } /* Read new chunks until we have enough samples */ while(codec->sample_buffer_end < codec->sample_buffer_start + samples) { if(!decode_frame(file, track)) break; } samples_decoded = (codec->sample_buffer_end - codec->sample_buffer_start) < samples ? (codec->sample_buffer_end - codec->sample_buffer_start) : samples; samples_copied = samples; if(samples_copied > samples_decoded) samples_copied = samples_decoded; output = (float*)_output; for(i = 0; i < samples_copied; i++) { for(j = 0; j < track_map->channels; j++) { *(output++) = codec->sample_buffer[j][i]; } } file->atracks[track].last_position = file->atracks[track].current_position + samples_copied; return samples_copied; }/* Encoding part */#define ENCODE_SAMPLES 4096static int flush_header(quicktime_t * file, int track) { quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; while(ogg_stream_flush(&codec->enc_os, &codec->enc_og)) { codec->enc_header = realloc(codec->enc_header, codec->enc_header_len + codec->enc_og.header_len + codec->enc_og.body_len); memcpy(codec->enc_header + codec->enc_header_len, codec->enc_og.header, codec->enc_og.header_len); memcpy(codec->enc_header + codec->enc_header_len + codec->enc_og.header_len, codec->enc_og.body, codec->enc_og.body_len); codec->enc_header_len += codec->enc_og.header_len + codec->enc_og.body_len; } if(codec->write_OVHS) { lqt_log(file, LQT_LOG_INFO, LOG_DOMAIN, "Writing OVHS atom %d bytes\n", codec->enc_header_len); quicktime_wave_set_user_atom(track_map->track, "OVHS", codec->enc_header, codec->enc_header_len); codec->header_written = 1; } return 0; }static int flush_data(quicktime_t * file, int track) { int64_t new_encoded_samples; int result = 0; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_trak_t *trak = track_map->track; quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; while(vorbis_analysis_blockout(&codec->enc_vd, &codec->enc_vb) == 1) { /* While there is compressed data available... */ // vorbis_analysis(&codec->enc_vb, &codec->enc_op); vorbis_analysis(&codec->enc_vb, NULL); // vorbis_analysis(&codec->enc_vb, &codec->enc_op); vorbis_bitrate_addblock(&codec->enc_vb); while(vorbis_bitrate_flushpacket(&codec->enc_vd, &codec->enc_op)) { /* While packets are available */ ogg_stream_packetin(&codec->enc_os, &codec->enc_op); } } while(!result) { // ogg_stream_flush(&codec->enc_os, &codec->enc_og); // break; /* While pages are available */ if(!ogg_stream_flush(&codec->enc_os, &codec->enc_og)) break; if(!codec->chunk_started) { codec->chunk_started = 1; lqt_start_audio_vbr_chunk(file, track); quicktime_write_chunk_header(file, trak, &codec->chunk_atom); } lqt_start_audio_vbr_frame(file, track); if(!codec->header_written) { codec->header_written = 1; result = !quicktime_write_data(file, codec->enc_header, codec->enc_header_len); } result = !quicktime_write_data(file, codec->enc_og.header, codec->enc_og.header_len); if(!result) { result = !quicktime_write_data(file, codec->enc_og.body, codec->enc_og.body_len); } new_encoded_samples = codec->enc_os.granulepos; lqt_finish_audio_vbr_frame(file, track, new_encoded_samples - codec->encoded_samples); codec->encoded_samples = new_encoded_samples; if(ogg_page_eos(&codec->enc_og)) break; } return result; }static void flush_audio(quicktime_t * file, int track) { quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; float ** output; int i; output = vorbis_analysis_buffer(&codec->enc_vd, codec->enc_samples_in_buffer); for(i = 0; i < track_map->channels; i++) { memcpy(output[i], codec->sample_buffer[i], sizeof(float) * codec->enc_samples_in_buffer); } vorbis_analysis_wrote(&codec->enc_vd, codec->enc_samples_in_buffer); codec->enc_samples_in_buffer = 0; flush_data(file, track); }static int encode(quicktime_t *file, void *_input, long samples, int track) { int i, j; int samples_copied, samples_to_copy; int result = 0; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_trak_t *trak = track_map->track; quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; int samplerate = track_map->samplerate; float * input; if(!codec->encode_initialized) { ogg_packet header; ogg_packet header_comm; ogg_packet header_code; codec->encode_initialized = 1; lqt_init_vbr_audio(file, track); if(file->file_type == LQT_FILE_AVI) trak->mdia.minf.stbl.stsd.table[0].sample_size = 0; vorbis_info_init(&codec->enc_vi); if(codec->use_vbr) { result = vorbis_encode_setup_managed(&codec->enc_vi, track_map->channels, samplerate, codec->max_bitrate, codec->nominal_bitrate, codec->min_bitrate); result |= vorbis_encode_ctl(&codec->enc_vi, OV_ECTL_RATEMANAGE_AVG, NULL); result |= vorbis_encode_setup_init(&codec->enc_vi); } else { vorbis_encode_init(&codec->enc_vi, track_map->channels, samplerate, codec->max_bitrate, codec->nominal_bitrate, codec->min_bitrate); } vorbis_comment_init(&codec->enc_vc); vorbis_analysis_init(&codec->enc_vd, &codec->enc_vi); vorbis_block_init(&codec->enc_vd, &codec->enc_vb); // srand(time(NULL)); ogg_stream_init(&codec->enc_os, rand()); vorbis_analysis_headerout(&codec->enc_vd, &codec->enc_vc, &header, &header_comm, &header_code); ogg_stream_packetin(&codec->enc_os, &header); ogg_stream_packetin(&codec->enc_os, &header_comm); ogg_stream_packetin(&codec->enc_os, &header_code); // FLUSH_OGG1 flush_header(file, track); codec->sample_buffer = alloc_sample_buffer(codec->sample_buffer, track_map->channels, ENCODE_SAMPLES, &codec->sample_buffer_alloc); } samples_copied = 0; while(samples_copied < samples) { samples_to_copy = samples - samples_copied; if(samples_to_copy > ENCODE_SAMPLES - codec->enc_samples_in_buffer) samples_to_copy = ENCODE_SAMPLES - codec->enc_samples_in_buffer; input = ((float*)_input + samples_copied * track_map->channels); for(j = 0; j < samples_to_copy; j++) { for(i = 0; i < track_map->channels; i++) codec->sample_buffer[i][codec->enc_samples_in_buffer + j] = *(input++); } samples_copied += samples_to_copy; codec->enc_samples_in_buffer += samples_to_copy; if(codec->enc_samples_in_buffer >= ENCODE_SAMPLES) flush_audio(file, track); } result = 0; // Wrote a chunk. if(codec->chunk_started) { quicktime_write_chunk_footer(file, trak, track_map->current_chunk, &codec->chunk_atom, track_map->vbr_num_frames); track_map->current_chunk++; codec->chunk_started = 0; } return result; }static int set_parameter(quicktime_t *file, int track, const char *key, const void *value){ quicktime_audio_map_t *atrack = &(file->atracks[track]); quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv; if(!strcasecmp(key, "vorbis_vbr")) codec->use_vbr = *(int*)value; else if(!strcasecmp(key, "vorbis_bitrate")) codec->nominal_bitrate = *(int*)value; else if(!strcasecmp(key, "vorbis_max_bitrate")) codec->max_bitrate = *(int*)value; else if(!strcasecmp(key, "vorbis_min_bitrate")) codec->min_bitrate = *(int*)value; return 0;}static int flush(quicktime_t *file, int track){ quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; quicktime_trak_t *trak = track_map->track; flush_audio(file, track); vorbis_analysis_wrote(&codec->enc_vd,0); flush_data(file, track); // FLUSH_OGG2 if(codec->chunk_started) { quicktime_write_chunk_footer(file, trak, track_map->current_chunk, &codec->chunk_atom, track_map->vbr_num_frames); track_map->current_chunk++; codec->chunk_started = 0; return 1; } return 0;}void quicktime_init_codec_vorbis(quicktime_audio_map_t *atrack){ quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec; quicktime_vorbis_codec_t *codec; char *compressor = atrack->track->mdia.minf.stbl.stsd.table[0].format;/* Init public items */ codec_base->priv = calloc(1, sizeof(quicktime_vorbis_codec_t)); codec_base->delete_acodec = delete_codec; codec_base->decode_audio = decode; codec_base->encode_audio = encode; codec_base->set_parameter = set_parameter; codec_base->flush = flush; codec = codec_base->priv; codec->nominal_bitrate = 128000; codec->max_bitrate = -1; codec->min_bitrate = -1; atrack->sample_format = LQT_SAMPLE_FLOAT; if(quicktime_match_32(compressor, "OggV")) { codec->write_OVHS = 1; } /* Set Vorbis 5.1 channel mapping */ if(atrack->channels == 6) { if(!atrack->channel_setup) { atrack->channel_setup = calloc(6, sizeof(*atrack->channel_setup)); atrack->channel_setup[0] = LQT_CHANNEL_FRONT_LEFT; atrack->channel_setup[1] = LQT_CHANNEL_FRONT_CENTER; atrack->channel_setup[2] = LQT_CHANNEL_FRONT_RIGHT; atrack->channel_setup[3] = LQT_CHANNEL_LFE; atrack->channel_setup[4] = LQT_CHANNEL_BACK_LEFT; atrack->channel_setup[5] = LQT_CHANNEL_BACK_RIGHT; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -