📄 audio.c
字号:
num_samples += 8192; new_samples = num_samples + AVCODEC_MAX_AUDIO_FRAME_SIZE / (2 * track_map->channels); /* Reallocate sample buffer */ if(codec->sample_buffer_alloc < codec->sample_buffer_end - codec->sample_buffer_start + new_samples) { codec->sample_buffer_alloc = codec->sample_buffer_end - codec->sample_buffer_start + new_samples; codec->sample_buffer = realloc(codec->sample_buffer, 2 * codec->sample_buffer_alloc * track_map->channels); } /* Decode this */ bytes_used = 0; while(1) { /* BIG NOTE: We pass extra FF_INPUT_BUFFER_PADDING_SIZE for the buffer size because we know, that lqt_read_audio_chunk allocates 16 extra bytes for us */ /* Some really broken mp3 files have the header bytes split across 2 chunks */ if(codec->avctx->codec_id == CODEC_ID_MP3) { if(codec->bytes_in_chunk_buffer < 4) { if(codec->bytes_in_chunk_buffer > 0) memmove(codec->chunk_buffer, codec->chunk_buffer + bytes_used, codec->bytes_in_chunk_buffer); return 1; } bytes_skipped = 0; while(1) { if(!codec->have_mpeg_header) { if(decode_header(&mph, &(codec->chunk_buffer[bytes_used]), NULL)) { memcpy(&(codec->mph), &mph, sizeof(mph)); codec->have_mpeg_header = 1; break; } } else if(decode_header(&mph, &(codec->chunk_buffer[bytes_used]), &(codec->mph))) break; bytes_used++; codec->bytes_in_chunk_buffer--; bytes_skipped++; if(codec->bytes_in_chunk_buffer <= 4) { if(codec->bytes_in_chunk_buffer > 0) memmove(codec->chunk_buffer, codec->chunk_buffer + bytes_used, codec->bytes_in_chunk_buffer); return 1; } } if(codec->bytes_in_chunk_buffer < mph.frame_bytes) { if(codec->bytes_in_chunk_buffer > 0) memmove(codec->chunk_buffer, codec->chunk_buffer + bytes_used, codec->bytes_in_chunk_buffer); return 1; } } /* * decode an audio frame. return -1 if error, otherwise return the * number of bytes used. If no frame could be decompressed, * frame_size_ptr is zero. Otherwise, it is the decompressed frame * size in BYTES. */#if LIBAVCODEC_BUILD >= 3349760 bytes_decoded = codec->sample_buffer_alloc - (codec->sample_buffer_end - codec->sample_buffer_start); bytes_decoded *= 2 * track_map->channels;#else bytes_decoded = 0;#endif frame_bytes = DECODE_FUNC(codec->avctx, &(codec->sample_buffer[track_map->channels * (codec->sample_buffer_end - codec->sample_buffer_start)]), &bytes_decoded, &(codec->chunk_buffer[bytes_used]), codec->bytes_in_chunk_buffer + FF_INPUT_BUFFER_PADDING_SIZE); if(frame_bytes < 0) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "avcodec_decode_audio error"); break; } bytes_used += frame_bytes; codec->bytes_in_chunk_buffer -= frame_bytes; if(bytes_decoded < 0) { if(codec->avctx->codec_id == CODEC_ID_MP3) { /* For mp3, bytes_decoded < 0 means, that the frame should be muted */ memset(&(codec->sample_buffer[track_map->channels * (codec->sample_buffer_end - codec->sample_buffer_start)]), 0, 2 * mph.samples_per_frame * track_map->channels); codec->sample_buffer_end += mph.samples_per_frame * track_map->channels; if(codec->bytes_in_chunk_buffer < 0) codec->bytes_in_chunk_buffer = 0; if(!codec->bytes_in_chunk_buffer) break; continue; } else { /* Incomplete frame, save the data for later use and exit here */ if(codec->bytes_in_chunk_buffer > 0) memmove(codec->chunk_buffer, codec->chunk_buffer + bytes_used, codec->bytes_in_chunk_buffer); return 1; } } /* This happens because ffmpeg adds FF_INPUT_BUFFER_PADDING_SIZE to the bytes returned */ if(codec->bytes_in_chunk_buffer < 0) codec->bytes_in_chunk_buffer = 0; if(bytes_decoded < 0) { if(codec->bytes_in_chunk_buffer > 0) codec->bytes_in_chunk_buffer = 0; break; } samples_decoded += (bytes_decoded / (track_map->channels * 2)); codec->sample_buffer_end += (bytes_decoded / (track_map->channels * 2)); if((int)(codec->sample_buffer_end - codec->sample_buffer_start) > codec->sample_buffer_alloc) lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "BUUUUG, buffer overflow, %d %d", (int)(codec->sample_buffer_end - codec->sample_buffer_start), codec->sample_buffer_alloc); if(!codec->bytes_in_chunk_buffer) break; } // track_map->current_chunk++; return samples_decoded; }static int lqt_ffmpeg_decode_audio(quicktime_t *file, void * output, long samples, int track) { uint8_t * header; uint32_t header_len; int samples_decoded; // int result = 0; int64_t chunk_sample; /* For seeking only */ quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_ffmpeg_audio_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; int channels = file->atracks[track].channels; // int64_t total_samples; int samples_to_skip; int samples_to_move; if(!output) /* Global initialization */ { return 0; } /* Initialize codec */ if(!codec->initialized) { /* Set some mandatory variables */ codec->avctx->channels = quicktime_track_channels(file, track); codec->avctx->sample_rate = quicktime_sample_rate(file, track); if(track_map->track->mdia.minf.stbl.stsd.table[0].version == 1) { if(track_map->track->mdia.minf.stbl.stsd.table[0].audio_bytes_per_frame) codec->avctx->block_align = track_map->track->mdia.minf.stbl.stsd.table[0].audio_bytes_per_frame; } // priv->ctx->block_align = s->data.audio.block_align; // priv->ctx->bit_rate = s->codec_bitrate;#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0) codec->avctx->bits_per_sample = quicktime_audio_bits(file, track);#else codec->avctx->bits_per_coded_sample = quicktime_audio_bits(file, track);#endif /* Some codecs need extra stuff */ if(codec->decoder->id == CODEC_ID_ALAC) { header = quicktime_wave_get_user_atom(track_map->track, "alac", &header_len); if(header) { codec->avctx->extradata = header; codec->avctx->extradata_size = header_len; } } if(codec->decoder->id == CODEC_ID_QDM2) { header = quicktime_wave_get_user_atom(track_map->track, "QDCA", &header_len); if(header) { codec->extradata = malloc(header_len + 12); /* frma atom */ codec->extradata[0] = 0x00; codec->extradata[1] = 0x00; codec->extradata[2] = 0x00; codec->extradata[3] = 0x0C; memcpy(codec->extradata + 4, "frmaQDM2", 8); /* QDCA atom */ memcpy(codec->extradata + 12, header, header_len); codec->avctx->extradata = codec->extradata; codec->avctx->extradata_size = header_len + 12; } } // memcpy(&(codec->com.ffcodec_enc), &(codec->com.params), sizeof(AVCodecContext)); if(avcodec_open(codec->avctx, codec->decoder) != 0) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "Avcodec open failed"); return 0; } // codec->sample_buffer_offset = 0; codec->initialized = 1; } /* Check if we have to reposition the stream */ if(track_map->last_position != track_map->current_position) { if((track_map->current_position < codec->sample_buffer_start) || (track_map->current_position + samples >= codec->sample_buffer_end)) { if(lqt_audio_is_vbr(file, track)) lqt_chunk_of_sample_vbr(&chunk_sample, &(track_map->current_chunk), 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); codec->sample_buffer_start = chunk_sample; codec->sample_buffer_end = chunk_sample; codec->bytes_in_chunk_buffer = 0; if(lqt_audio_is_vbr(file, track)) decode_chunk_vbr(file, track); else decode_chunk(file, track); } } /* Flush unneeded samples */ samples_to_skip = 0; if(track_map->current_position > codec->sample_buffer_start) { samples_to_skip = track_map->current_position - codec->sample_buffer_start; if(samples_to_skip > (int)(codec->sample_buffer_end - codec->sample_buffer_start)) samples_to_skip = (int)(codec->sample_buffer_end - codec->sample_buffer_start); if(codec->sample_buffer_end > track_map->current_position) { samples_to_move = codec->sample_buffer_end - track_map->current_position; memmove(codec->sample_buffer, &(codec->sample_buffer[samples_to_skip * channels]), samples_to_move * channels * sizeof(int16_t)); } codec->sample_buffer_start += samples_to_skip; } samples_to_skip = track_map->current_position - codec->sample_buffer_start; /* Read new chunks until we have enough samples */ while(codec->sample_buffer_end - codec->sample_buffer_start < samples + samples_to_skip) { // if(track_map->current_chunk >= track_map->track->mdia.minf.stbl.stco.total_entries) // return 0; if(lqt_audio_is_vbr(file, track)) { if(!decode_chunk_vbr(file, track)) break; } else { if(!decode_chunk(file, track)) break; } } samples_decoded = codec->sample_buffer_end - codec->sample_buffer_start - samples_to_skip; if(samples_decoded <= 0) { track_map->last_position = track_map->current_position; return 0; } if(samples_decoded > samples) samples_decoded = samples; /* Deinterleave into the buffer */ // deinterleave(output_i, output_f, codec->sample_buffer + (track_map->channels * samples_to_skip), // channels, samples_decoded); memcpy(output, codec->sample_buffer + (channels * samples_to_skip), channels * samples_decoded * 2); track_map->last_position = track_map->current_position + samples_decoded; return samples_decoded; // #endif }/* * Encoding part */static int lqt_ffmpeg_encode_audio(quicktime_t *file, void * input, long samples, int track) { int result = -1; quicktime_audio_map_t *track_map = &(file->atracks[track]); quicktime_ffmpeg_audio_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv; quicktime_trak_t *trak = track_map->track; int channels = file->atracks[track].channels; quicktime_atom_t chunk_atom; int frame_bytes; int samples_done = 0; int samples_encoded; /* Initialize encoder */ if(!codec->initialized) { codec->avctx->sample_rate = track_map->samplerate; codec->avctx->channels = channels; if(avcodec_open(codec->avctx, codec->encoder) != 0) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "Avcodec open failed"); return -1; } codec->initialized = 1; /* One frame is: bitrate * frame_samples / (samplerate * 8) + 1024 */#if 0 // PATCH 1 codec->chunk_buffer_alloc = (codec->avctx->bit_rate * codec->avctx->frame_size / (codec->avctx->sample_rate * 8)) + 1024;#else codec->chunk_buffer_alloc = ( codec->avctx->frame_size * sizeof( int16_t ) * codec->avctx->channels );#endif codec->chunk_buffer = malloc(codec->chunk_buffer_alloc); } /* Allocate sample buffer if necessary */// PATCH 2 if(codec->sample_buffer_alloc < (codec->samples_in_buffer + samples)) { codec->sample_buffer_alloc = codec->samples_in_buffer + samples + 16; codec->sample_buffer = realloc(codec->sample_buffer, codec->sample_buffer_alloc * channels * sizeof(int16_t)); } /* Interleave */ // interleave(&(codec->sample_buffer[codec->samples_in_buffer * channels]), // input_i, input_f, samples, channels); memcpy(codec->sample_buffer + codec->samples_in_buffer * channels, input, samples * channels * 2); codec->samples_in_buffer += samples; /* Encode */ while(codec->samples_in_buffer >= codec->avctx->frame_size) { frame_bytes = avcodec_encode_audio(codec->avctx, codec->chunk_buffer, codec->chunk_buffer_alloc, &(codec->sample_buffer[samples_done*channels])); if(frame_bytes > 0) { quicktime_write_chunk_header(file, trak, &chunk_atom);#if 0 // PATCH 3 if(codec->avctx->frame_size == 1) samples_encoded = codec->samples_in_buffer; else#endif samples_encoded = codec->avctx->frame_size; samples_done += samples_encoded; codec->samples_in_buffer -= samples_encoded; result = !quicktime_write_data(file, codec->chunk_buffer, frame_bytes); quicktime_write_chunk_footer(file, trak, file->atracks[track].current_chunk, &chunk_atom, samples_encoded); file->atracks[track].current_chunk++; } } if(codec->samples_in_buffer && samples_done) memmove(codec->sample_buffer, &(codec->sample_buffer[samples_done*channels]), codec->samples_in_buffer * sizeof(int16_t) * channels); return result; }void quicktime_init_audio_codec_ffmpeg(quicktime_audio_map_t *atrack, AVCodec *encoder, AVCodec *decoder){ quicktime_ffmpeg_audio_codec_t *codec; avcodec_init(); codec = calloc(1, sizeof(quicktime_ffmpeg_audio_codec_t)); if(!codec) return; codec->encoder = encoder; codec->decoder = decoder; codec-> avctx = avcodec_alloc_context(); ((quicktime_codec_t*)atrack->codec)->priv = (void *)codec; ((quicktime_codec_t*)atrack->codec)->delete_acodec = lqt_ffmpeg_delete_audio; if(encoder) ((quicktime_codec_t*)atrack->codec)->encode_audio = lqt_ffmpeg_encode_audio; if(decoder) ((quicktime_codec_t*)atrack->codec)->decode_audio = lqt_ffmpeg_decode_audio; ((quicktime_codec_t*)atrack->codec)->set_parameter = set_parameter; atrack->sample_format = LQT_SAMPLE_INT16;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -