Libav 0.7.1
|
00001 /* 00002 * SoX native format muxer 00003 * Copyright (c) 2009 Daniel Verkamp <daniel@drv.nu> 00004 * 00005 * Based on libSoX sox-fmt.c 00006 * Copyright (c) 2008 robs@users.sourceforge.net 00007 * 00008 * This file is part of Libav. 00009 * 00010 * Libav is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * Libav is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with Libav; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00023 */ 00024 00032 #include "libavutil/intreadwrite.h" 00033 #include "libavutil/dict.h" 00034 #include "avformat.h" 00035 #include "avio_internal.h" 00036 #include "sox.h" 00037 00038 typedef struct { 00039 int64_t header_size; 00040 } SoXContext; 00041 00042 static int sox_write_header(AVFormatContext *s) 00043 { 00044 SoXContext *sox = s->priv_data; 00045 AVIOContext *pb = s->pb; 00046 AVCodecContext *enc = s->streams[0]->codec; 00047 AVDictionaryEntry *comment; 00048 size_t comment_len = 0, comment_size; 00049 00050 comment = av_dict_get(s->metadata, "comment", NULL, 0); 00051 if (comment) 00052 comment_len = strlen(comment->value); 00053 comment_size = (comment_len + 7) & ~7; 00054 00055 sox->header_size = SOX_FIXED_HDR + comment_size; 00056 00057 if (enc->codec_id == CODEC_ID_PCM_S32LE) { 00058 ffio_wfourcc(pb, ".SoX"); 00059 avio_wl32(pb, sox->header_size); 00060 avio_wl64(pb, 0); /* number of samples */ 00061 avio_wl64(pb, av_dbl2int(enc->sample_rate)); 00062 avio_wl32(pb, enc->channels); 00063 avio_wl32(pb, comment_size); 00064 } else if (enc->codec_id == CODEC_ID_PCM_S32BE) { 00065 ffio_wfourcc(pb, "XoS."); 00066 avio_wb32(pb, sox->header_size); 00067 avio_wb64(pb, 0); /* number of samples */ 00068 avio_wb64(pb, av_dbl2int(enc->sample_rate)); 00069 avio_wb32(pb, enc->channels); 00070 avio_wb32(pb, comment_size); 00071 } else { 00072 av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n"); 00073 return -1; 00074 } 00075 00076 if (comment_len) 00077 avio_write(pb, comment->value, comment_len); 00078 00079 for ( ; comment_size > comment_len; comment_len++) 00080 avio_w8(pb, 0); 00081 00082 avio_flush(pb); 00083 00084 return 0; 00085 } 00086 00087 static int sox_write_packet(AVFormatContext *s, AVPacket *pkt) 00088 { 00089 AVIOContext *pb = s->pb; 00090 avio_write(pb, pkt->data, pkt->size); 00091 return 0; 00092 } 00093 00094 static int sox_write_trailer(AVFormatContext *s) 00095 { 00096 SoXContext *sox = s->priv_data; 00097 AVIOContext *pb = s->pb; 00098 AVCodecContext *enc = s->streams[0]->codec; 00099 00100 if (s->pb->seekable) { 00101 /* update number of samples */ 00102 int64_t file_size = avio_tell(pb); 00103 int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL; 00104 avio_seek(pb, 8, SEEK_SET); 00105 if (enc->codec_id == CODEC_ID_PCM_S32LE) { 00106 avio_wl64(pb, num_samples); 00107 } else 00108 avio_wb64(pb, num_samples); 00109 avio_seek(pb, file_size, SEEK_SET); 00110 00111 avio_flush(pb); 00112 } 00113 00114 return 0; 00115 } 00116 00117 AVOutputFormat ff_sox_muxer = { 00118 "sox", 00119 NULL_IF_CONFIG_SMALL("SoX native format"), 00120 NULL, 00121 "sox", 00122 sizeof(SoXContext), 00123 CODEC_ID_PCM_S32LE, 00124 CODEC_ID_NONE, 00125 sox_write_header, 00126 sox_write_packet, 00127 sox_write_trailer, 00128 };