Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * SoX native format muxer
  3.  * Copyright (c) 2009 Daniel Verkamp <daniel@drv.nu>
  4.  *
  5.  * Based on libSoX sox-fmt.c
  6.  * Copyright (c) 2008 robs@users.sourceforge.net
  7.  *
  8.  * This file is part of FFmpeg.
  9.  *
  10.  * FFmpeg is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU Lesser General Public
  12.  * License as published by the Free Software Foundation; either
  13.  * version 2.1 of the License, or (at your option) any later version.
  14.  *
  15.  * FFmpeg is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.  * Lesser General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU Lesser General Public
  21.  * License along with FFmpeg; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23.  */
  24.  
  25. /**
  26.  * @file
  27.  * SoX native format muxer
  28.  * @author Daniel Verkamp
  29.  * @see http://wiki.multimedia.cx/index.php?title=SoX_native_intermediate_format
  30.  */
  31.  
  32. #include "libavutil/intreadwrite.h"
  33. #include "libavutil/intfloat.h"
  34. #include "libavutil/dict.h"
  35. #include "avformat.h"
  36. #include "avio_internal.h"
  37. #include "rawenc.h"
  38. #include "sox.h"
  39.  
  40. typedef struct {
  41.     int64_t header_size;
  42. } SoXContext;
  43.  
  44. static int sox_write_header(AVFormatContext *s)
  45. {
  46.     SoXContext *sox = s->priv_data;
  47.     AVIOContext *pb = s->pb;
  48.     AVCodecContext *enc = s->streams[0]->codec;
  49.     AVDictionaryEntry *comment;
  50.     size_t comment_len = 0, comment_size;
  51.  
  52.     comment = av_dict_get(s->metadata, "comment", NULL, 0);
  53.     if (comment)
  54.         comment_len = strlen(comment->value);
  55.     comment_size = FFALIGN(comment_len, 8);
  56.  
  57.     sox->header_size = SOX_FIXED_HDR + comment_size;
  58.  
  59.     if (enc->codec_id == AV_CODEC_ID_PCM_S32LE) {
  60.         ffio_wfourcc(pb, ".SoX");
  61.         avio_wl32(pb, sox->header_size);
  62.         avio_wl64(pb, 0); /* number of samples */
  63.         avio_wl64(pb, av_double2int(enc->sample_rate));
  64.         avio_wl32(pb, enc->channels);
  65.         avio_wl32(pb, comment_size);
  66.     } else if (enc->codec_id == AV_CODEC_ID_PCM_S32BE) {
  67.         ffio_wfourcc(pb, "XoS.");
  68.         avio_wb32(pb, sox->header_size);
  69.         avio_wb64(pb, 0); /* number of samples */
  70.         avio_wb64(pb, av_double2int(enc->sample_rate));
  71.         avio_wb32(pb, enc->channels);
  72.         avio_wb32(pb, comment_size);
  73.     } else {
  74.         av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n");
  75.         return -1;
  76.     }
  77.  
  78.     if (comment_len)
  79.         avio_write(pb, comment->value, comment_len);
  80.  
  81.     ffio_fill(pb, 0, comment_size - comment_len);
  82.  
  83.     avio_flush(pb);
  84.  
  85.     return 0;
  86. }
  87.  
  88. static int sox_write_trailer(AVFormatContext *s)
  89. {
  90.     SoXContext *sox = s->priv_data;
  91.     AVIOContext *pb = s->pb;
  92.     AVCodecContext *enc = s->streams[0]->codec;
  93.  
  94.     if (s->pb->seekable) {
  95.         /* update number of samples */
  96.         int64_t file_size = avio_tell(pb);
  97.         int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL;
  98.         avio_seek(pb, 8, SEEK_SET);
  99.         if (enc->codec_id == AV_CODEC_ID_PCM_S32LE) {
  100.             avio_wl64(pb, num_samples);
  101.         } else
  102.             avio_wb64(pb, num_samples);
  103.         avio_seek(pb, file_size, SEEK_SET);
  104.  
  105.         avio_flush(pb);
  106.     }
  107.  
  108.     return 0;
  109. }
  110.  
  111. AVOutputFormat ff_sox_muxer = {
  112.     .name              = "sox",
  113.     .long_name         = NULL_IF_CONFIG_SMALL("SoX native"),
  114.     .extensions        = "sox",
  115.     .priv_data_size    = sizeof(SoXContext),
  116.     .audio_codec       = AV_CODEC_ID_PCM_S32LE,
  117.     .video_codec       = AV_CODEC_ID_NONE,
  118.     .write_header      = sox_write_header,
  119.     .write_packet      = ff_raw_write_packet,
  120.     .write_trailer     = sox_write_trailer,
  121. };
  122.