⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 这个库实现了录象功能
💻 C
📖 第 1 页 / 共 2 页
字号:
  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 + -