00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00032 #include "libavutil/intreadwrite.h"
00033 #include "avformat.h"
00034 #include "avio_internal.h"
00035 #include "sox.h"
00036
00037 typedef struct {
00038 int64_t header_size;
00039 } SoXContext;
00040
00041 static int sox_write_header(AVFormatContext *s)
00042 {
00043 SoXContext *sox = s->priv_data;
00044 AVIOContext *pb = s->pb;
00045 AVCodecContext *enc = s->streams[0]->codec;
00046 AVMetadataTag *comment;
00047 size_t comment_len = 0, comment_size;
00048
00049 comment = av_metadata_get(s->metadata, "comment", NULL, 0);
00050 if (comment)
00051 comment_len = strlen(comment->value);
00052 comment_size = (comment_len + 7) & ~7;
00053
00054 sox->header_size = SOX_FIXED_HDR + comment_size;
00055
00056 if (enc->codec_id == CODEC_ID_PCM_S32LE) {
00057 ffio_wfourcc(pb, ".SoX");
00058 avio_wl32(pb, sox->header_size);
00059 avio_wl64(pb, 0);
00060 avio_wl64(pb, av_dbl2int(enc->sample_rate));
00061 avio_wl32(pb, enc->channels);
00062 avio_wl32(pb, comment_size);
00063 } else if (enc->codec_id == CODEC_ID_PCM_S32BE) {
00064 ffio_wfourcc(pb, "XoS.");
00065 avio_wb32(pb, sox->header_size);
00066 avio_wb64(pb, 0);
00067 avio_wb64(pb, av_dbl2int(enc->sample_rate));
00068 avio_wb32(pb, enc->channels);
00069 avio_wb32(pb, comment_size);
00070 } else {
00071 av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n");
00072 return -1;
00073 }
00074
00075 if (comment_len)
00076 avio_write(pb, comment->value, comment_len);
00077
00078 for ( ; comment_size > comment_len; comment_len++)
00079 avio_w8(pb, 0);
00080
00081 put_flush_packet(pb);
00082
00083 return 0;
00084 }
00085
00086 static int sox_write_packet(AVFormatContext *s, AVPacket *pkt)
00087 {
00088 AVIOContext *pb = s->pb;
00089 avio_write(pb, pkt->data, pkt->size);
00090 return 0;
00091 }
00092
00093 static int sox_write_trailer(AVFormatContext *s)
00094 {
00095 SoXContext *sox = s->priv_data;
00096 AVIOContext *pb = s->pb;
00097 AVCodecContext *enc = s->streams[0]->codec;
00098
00099 if (!url_is_streamed(s->pb)) {
00100
00101 int64_t file_size = avio_tell(pb);
00102 int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL;
00103 avio_seek(pb, 8, SEEK_SET);
00104 if (enc->codec_id == CODEC_ID_PCM_S32LE) {
00105 avio_wl64(pb, num_samples);
00106 } else
00107 avio_wb64(pb, num_samples);
00108 avio_seek(pb, file_size, SEEK_SET);
00109
00110 put_flush_packet(pb);
00111 }
00112
00113 return 0;
00114 }
00115
00116 AVOutputFormat ff_sox_muxer = {
00117 "sox",
00118 NULL_IF_CONFIG_SMALL("SoX native format"),
00119 NULL,
00120 "sox",
00121 sizeof(SoXContext),
00122 CODEC_ID_PCM_S32LE,
00123 CODEC_ID_NONE,
00124 sox_write_header,
00125 sox_write_packet,
00126 sox_write_trailer,
00127 };