lame_codec.c
来自「这个库实现了录象功能」· C语言 代码 · 共 685 行 · 第 1/2 页
C
685 行
chunk_ptr = codec->encoder_output; while(codec->encoder_output_size > 4) { if(!decode_header(&h, chunk_ptr)) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "Ouch: lame created non mp3 data\n"); break; } if(codec->encoder_output_size >= h.frame_bytes) { codec->encoder_output_size -= h.frame_bytes; chunk_ptr += h.frame_bytes; chunk_bytes += h.frame_bytes; chunk_samples += h.samples_per_frame; } else break; } if(chunk_ptr > codec->encoder_output) { if(track_map->track->strl) { quicktime_write_chunk_header(file, track_map->track, &chunk_atom); result = !quicktime_write_data(file, codec->encoder_output, chunk_bytes); quicktime_write_chunk_footer(file, track_map->track, track_map->current_chunk, &chunk_atom, chunk_samples); if(file->total_riffs == 1) { track_map->track->strl->strh.dwLength += chunk_bytes; } } else { lqt_start_audio_vbr_chunk(file, track); quicktime_write_chunk_header(file, track_map->track, &chunk_atom); lqt_start_audio_vbr_frame(file, track); result = !quicktime_write_data(file, codec->encoder_output, chunk_bytes); if(samples < 0) { lqt_finish_audio_vbr_frame(file, track, chunk_samples); quicktime_write_chunk_footer(file, track_map->track, track_map->current_chunk, &chunk_atom, track_map->vbr_num_frames); codec->samples_written += chunk_samples; } else { lqt_finish_audio_vbr_frame(file, track, samples); quicktime_write_chunk_footer(file, track_map->track, track_map->current_chunk, &chunk_atom, track_map->vbr_num_frames); codec->samples_written += samples; } } track_map->current_chunk++; /* Adjust mp3 buffer */ if(codec->encoder_output_size) memmove(codec->encoder_output, chunk_ptr, codec->encoder_output_size); } return result; }#define PUT_16_LE(num, ptr) \ptr[0] = num & 0xff; \ptr[1] = (num >> 8) & 0xff;\ptr+=2;#define PUT_32_LE(num, ptr) \ptr[0] = num & 0xff; \ptr[1] = (num >> 8) & 0xff;\ptr[2] = (num >> 16) & 0xff;\ptr[3] = (num >> 24) & 0xff;\ptr+=4;/* nanosoft style mp3 definitions */#define MPEGLAYER3_ID_UNKNOWN 0#define MPEGLAYER3_ID_MPEG 1#define MPEGLAYER3_ID_CONSTANTFRAMESIZE 2#define MPEGLAYER3_FLAG_PADDING_ISO 0x00000000#define MPEGLAYER3_FLAG_PADDING_ON 0x00000001#define MPEGLAYER3_FLAG_PADDING_OFF 0x00000002static int encode(quicktime_t *file, void * _input, long samples, int track) { int16_t * input; int result = 0; int encoded_size; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_trak_t *trak = track_map->track; quicktime_mp3_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; int i; uint8_t extradata[12]; uint8_t * extradata_ptr; uint32_t tmp; int mpeg_version; if(!codec->encode_initialized) { if(!trak->strl) lqt_init_vbr_audio(file, track); codec->encode_initialized = 1; codec->lame_global = lame_init(); if(trak->strl || (codec->bitrate_mode == vbr_off)) { lame_set_VBR(codec->lame_global, vbr_off); lame_set_brate(codec->lame_global, codec->bitrate / 1000); } else if(codec->bitrate_mode == vbr_default) { lame_set_VBR(codec->lame_global, vbr_default); lame_set_VBR_q(codec->lame_global, codec->quality_vbr); } else if(codec->bitrate_mode == vbr_abr) { lame_set_VBR(codec->lame_global, vbr_abr); lame_set_VBR_min_bitrate_kbps(codec->lame_global, codec->bitrate_min/1000); lame_set_VBR_max_bitrate_kbps(codec->lame_global, codec->bitrate_max/1000); } lame_set_quality(codec->lame_global, codec->quality); lame_set_in_samplerate(codec->lame_global, track_map->samplerate); lame_set_out_samplerate(codec->lame_global, track_map->samplerate); lame_set_bWriteVbrTag(codec->lame_global, 0); /* Also support Mono streams */ codec->stereo = (trak->mdia.minf.stbl.stsd.table[0].channels == 1) ? 0 : 1; lame_set_num_channels(codec->lame_global, (codec->stereo ? 2 : 1)); // lame_set_padding_type(codec->lame_global, PAD_ALL); // PAD_NO | PAD_ALL | PAD_ADJUST if((result = lame_init_params(codec->lame_global)) < 0) lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "lame_init_params returned %d\n", result); // codec->encoded_header = mpeg3_new_layer(); codec->samples_per_frame = lame_get_framesize(codec->lame_global); /* Initialize AVI header */ if(trak->strl) { /* strh stuff */ trak->strl->strh.dwRate = codec->bitrate / 8; trak->strl->strh.dwScale = 1; trak->strl->strh.dwSampleSize = 1; /* WAVEFORMATEX stuff */ trak->strl->strf.wf.f.WAVEFORMAT.nBlockAlign = 1; trak->strl->strf.wf.f.WAVEFORMAT.nAvgBytesPerSec = codec->bitrate / 8; trak->strl->strf.wf.f.PCMWAVEFORMAT.wBitsPerSample = 0; /* Extradata (completely unneccesary for decoding) */ mpeg_version = lame_get_version(codec->lame_global); extradata_ptr = extradata; tmp = MPEGLAYER3_ID_MPEG; // WORD wID PUT_16_LE(tmp, extradata_ptr); tmp = MPEGLAYER3_FLAG_PADDING_ISO; // DWORD fdwFlags; PUT_32_LE(tmp, extradata_ptr); switch(mpeg_version) { case 0: // MPEG-2 tmp = ((144000 / 2) * (codec->bitrate/1000)) / track_map->samplerate; // WORD nBlockSize; break; case 1: // MPEG-1 tmp = ((144000 / 1) * (codec->bitrate/1000)) / track_map->samplerate; // WORD nBlockSize; break; case 2: // MPEG-2.5 tmp = ((144000 / 4) * (codec->bitrate/1000)) / track_map->samplerate; // WORD nBlockSize; break; } PUT_16_LE(tmp, extradata_ptr); tmp = 1; // WORD nFramesPerBlock; PUT_16_LE(tmp, extradata_ptr); tmp = 1393; // WORD nCodecDelay; PUT_16_LE(tmp, extradata_ptr); quicktime_strf_set_audio_extradata(&trak->strl->strf, extradata, 12); } } /* Reallocate output if necessary */ encoded_size = (5*samples)/4 + 7200; if(codec->encoder_output_alloc < encoded_size + codec->encoder_output_size) { codec->encoder_output_alloc = encoded_size + codec->encoder_output_size + 16; codec->encoder_output = realloc(codec->encoder_output, codec->encoder_output_alloc); } if(codec->input_buffer_alloc < samples) { codec->input_buffer_alloc = samples + 16; codec->input_buffer[0] = realloc(codec->input_buffer[0], codec->input_buffer_alloc * sizeof(*codec->input_buffer[0])); if(codec->stereo) codec->input_buffer[1] = realloc(codec->input_buffer[1], codec->input_buffer_alloc * sizeof(*codec->input_buffer[1])); } input = (int16_t*)_input; if(codec->stereo) { for(i = 0; i < samples; i++) { codec->input_buffer[0][i] = *(input++); codec->input_buffer[1][i] = *(input++); } } else { for(i = 0; i < samples; i++) codec->input_buffer[0][i] = *(input++); } result = lame_encode_buffer(codec->lame_global, codec->input_buffer[0], codec->stereo ? codec->input_buffer[1] : codec->input_buffer[0], samples, codec->encoder_output + codec->encoder_output_size, codec->encoder_output_alloc - codec->encoder_output_size); codec->samples_read += samples; if(result > 0) { codec->encoder_output_size += result; result = write_data(file, track, codec, -1); } 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_mp3_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv; if(!strcasecmp(key, "mp3_bitrate_mode")) { if(!strcmp((char*)value, "CBR")) codec->bitrate_mode = vbr_off; else if(strcmp((char*)value, "ABR")) codec->bitrate_mode = vbr_abr; else if(strcmp((char*)value, "VBR")) codec->bitrate_mode = vbr_default; } else if(!strcasecmp(key, "mp3_bitrate")) codec->bitrate = *(int*)value; else if(!strcasecmp(key, "mp3_bitrate_min")) codec->bitrate_min = *(int*)value; else if(!strcasecmp(key, "mp3_bitrate_max")) codec->bitrate_max = *(int*)value; else if(!strcasecmp(key, "mp3_quality")) codec->quality = *(int*)value; else if(!strcasecmp(key, "mp3_quality_vbr")) codec->quality_vbr = *(int*)value; return 0; }static int flush(quicktime_t *file, int track) { int result = 0; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_mp3_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; if(codec->encode_initialized) { // samples_left = lame_get_mf_samples_to_encode(codec->lame_global); result = lame_encode_flush(codec->lame_global, codec->encoder_output + codec->encoder_output_size, codec->encoder_output_alloc); /* Check if more frames arrived */ if(result > 0) { codec->encoder_output_size += result; write_data(file, track, codec, codec->samples_read - codec->samples_written); return 1; } } return 0; }void quicktime_init_codec_lame(quicktime_audio_map_t *atrack) { quicktime_mp3_codec_t *codec; /* Init public items */ ((quicktime_codec_t*)atrack->codec)->priv = calloc(1, sizeof(quicktime_mp3_codec_t)); ((quicktime_codec_t*)atrack->codec)->delete_acodec = delete_codec; // ((quicktime_codec_t*)atrack->codec)->decode_audio = decode; ((quicktime_codec_t*)atrack->codec)->encode_audio = encode; ((quicktime_codec_t*)atrack->codec)->set_parameter = set_parameter; ((quicktime_codec_t*)atrack->codec)->flush = flush; codec = ((quicktime_codec_t*)atrack->codec)->priv; codec->bitrate = 256000; codec->quality = 0; atrack->sample_format = LQT_SAMPLE_INT16; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?