예제 #1
0
libspectrum_error
libspectrum_csw_write( libspectrum_byte **buffer, size_t *length,
                       libspectrum_tape *tape )
{
    libspectrum_error error;
    libspectrum_dword sample_rate;
    size_t length_offset;

    libspectrum_byte *ptr = *buffer;

    size_t signature_length = strlen( csw_signature );

    /* First, write the .csw signature and the rest of the header */
    libspectrum_make_room( buffer, signature_length + 29, &ptr, length );

    memcpy( ptr, csw_signature, signature_length );
    ptr += signature_length;

    *ptr++ = 2;		/* Major version number */
    *ptr++ = 0;		/* Minor version number */

    /* sample rate */
    sample_rate = find_sample_rate( tape );
    libspectrum_write_dword( &ptr, sample_rate );

    /* Store where the total number of pulses (after decompression) will
       be written, and skip over those bytes */
    length_offset = ptr - *buffer;
    ptr += sizeof(libspectrum_dword);

    /* compression type */
#ifdef HAVE_ZLIB_H
    *ptr++ = 2;		/* Z-RLE */
#else
    *ptr++ = 1;		/* RLE */
#endif

    /* flags */
    *ptr++ = 0;		/* No flags */

    /* header extension length in bytes */
    *ptr++ = 0;		/* No header extension */

    /* encoding application description */
    memset( ptr, 0, 16 );
    ptr += 16; /* No creator for now */

    /* header extension data is zero so on to the data */

    error = csw_write_body( buffer, length, tape, sample_rate, length_offset, ptr );
    if( error != LIBSPECTRUM_ERROR_NONE ) return error;

    return LIBSPECTRUM_ERROR_NONE;
}
예제 #2
0
파일: stream.c 프로젝트: EQ4/musicd
bool stream_transcode(stream_t *stream, codec_type_t codec_type, int bitrate)
{
  int result;
  enum AVCodecID dst_codec_id;
  AVCodec *dst_codec = NULL;
  AVCodecContext *decoder = NULL, *encoder = NULL;
  enum AVSampleFormat dst_sample_fmt;
  int dst_sample_rate;
  resampler_t *resampler = NULL;

  if (codec_type == CODEC_TYPE_MP3) {
    dst_codec_id = AV_CODEC_ID_MP3;
  } else if (codec_type == CODEC_TYPE_OGG_VORBIS) {
    dst_codec_id = AV_CODEC_ID_VORBIS;
  } else if (codec_type == CODEC_TYPE_FLAC) {
    dst_codec_id = AV_CODEC_ID_FLAC;
  } else if (codec_type == CODEC_TYPE_AAC) {
    dst_codec_id = AV_CODEC_ID_AAC;
  } else if (codec_type == CODEC_TYPE_OPUS) {
    dst_codec_id = AV_CODEC_ID_OPUS;
  } else {
    musicd_log(LOG_ERROR, "stream", "unsupported encoder requested");
    return false;;
  }

  dst_codec = avcodec_find_encoder(dst_codec_id);
  if (!dst_codec) {
    musicd_log(LOG_ERROR, "stream", "requested encoder not found");
    return false;
  }

  decoder = stream->src_ctx->streams[0]->codec;

  /* Try to figure out common sample format to skip format conversion */
  decoder->request_sample_fmt =
    find_common_sample_fmt(stream->src_codec->sample_fmts,
                           dst_codec->sample_fmts);

  result = avcodec_open2(decoder, stream->src_codec, NULL);
  if (result < 0) {
    musicd_log(LOG_ERROR, "stream", "can't open decoder: %s",
               strerror(AVUNERROR(result)));
    goto fail;
  }

  dst_sample_fmt = find_sample_fmt(decoder->sample_fmt,
                                   dst_codec->sample_fmts);
  dst_sample_rate = find_sample_rate(decoder->sample_rate,
                                     dst_codec->supported_samplerates);

  /** @todo FIXME Hard-coded values. */
  if (bitrate < 64000 || bitrate > 320000) {
    bitrate = 196000;
  }

  if (decoder->channel_layout == 0) {
    decoder->channel_layout = av_get_default_channel_layout(decoder->channels);
  }

  encoder = avcodec_alloc_context3(dst_codec);
  encoder->sample_rate = dst_sample_rate;
  encoder->channels = decoder->channels;
  encoder->sample_fmt = dst_sample_fmt;
  encoder->channel_layout = decoder->channel_layout;
  encoder->bit_rate = bitrate;

  result = avcodec_open2(encoder, dst_codec, NULL);
  if (result < 0) {
    musicd_log(LOG_ERROR, "stream", "can't open encoder: %s",
               strerror(AVUNERROR(result)));
    goto fail;
  }

  if (decoder->channel_layout != encoder->channel_layout ||
      decoder->sample_fmt != encoder->sample_fmt ||
      decoder->sample_rate != encoder->sample_rate) {

    resampler = resampler_alloc();
    av_opt_set_int(resampler, "in_channel_layout", decoder->channel_layout, 0);
    av_opt_set_int(resampler, "out_channel_layout", encoder->channel_layout, 0);
    av_opt_set_int(resampler, "in_sample_rate", decoder->sample_rate, 0);
    av_opt_set_int(resampler, "out_sample_rate", encoder->sample_rate, 0);
    av_opt_set_int(resampler, "in_sample_fmt", decoder->sample_fmt, 0);
    av_opt_set_int(resampler, "out_sample_fmt", encoder->sample_fmt, 0);

    result = resampler_init(resampler);
    if (result < 0) {
      musicd_log(LOG_ERROR, "stream", "can't open resampler: %s",
               strerror(AVUNERROR(result)));
      goto fail;
    }
    musicd_log(LOG_DEBUG, "stream",
               "resample: ch:%d(%d) rate:%d fmt:%d -> ch:%d(%d) rate:%d fmt:%d",
               decoder->channel_layout, decoder->channels,
               decoder->sample_rate, decoder->sample_fmt,
               encoder->channel_layout, encoder->channels,
               encoder->sample_rate, encoder->sample_fmt);
  }

  stream->decoder = decoder;
  stream->encoder = encoder;
  stream->dst_codec = dst_codec;
  stream->dst_codec_type = codec_type;
  stream->resampler = resampler;
  format_from_av(encoder, &stream->format);

  stream->src_buf = av_audio_fifo_alloc(encoder->sample_fmt, encoder->channels, encoder->frame_size);

  stream->decode_frame = avcodec_alloc_frame();

  if (stream->resampler) {
    /* The buffer will be allocated dynamically */
    stream->resample_frame = avcodec_alloc_frame();
  }

  int buf_size = av_samples_get_buffer_size(NULL, stream->encoder->channels,
                                                  stream->encoder->frame_size,
                                                  stream->encoder->sample_fmt, 0);
  stream->encode_buf = av_mallocz(buf_size);
  stream->encode_frame = avcodec_alloc_frame();
  stream->encode_frame->nb_samples = stream->encoder->frame_size;
  avcodec_fill_audio_frame(stream->encode_frame,
                           stream->encoder->channels,
                           stream->encoder->sample_fmt,
                           stream->encode_buf, buf_size, 0);
  return true;

fail:
  if (decoder) {
    avcodec_close(decoder);
  }
  if (encoder) {
    avcodec_close(encoder);
    av_free(encoder);
  }
  if (resampler) {
    resampler_free(&resampler);
  }
  return false;
}