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 "sox.h"
00035
00036 typedef struct {
00037 int64_t header_size;
00038 } SoXContext;
00039
00040 static int sox_write_header(AVFormatContext *s)
00041 {
00042 SoXContext *sox = s->priv_data;
00043 ByteIOContext *pb = s->pb;
00044 AVCodecContext *enc = s->streams[0]->codec;
00045 AVMetadataTag *comment;
00046 size_t comment_len = 0, comment_size;
00047
00048 comment = av_metadata_get(s->metadata, "comment", NULL, 0);
00049 if (comment)
00050 comment_len = strlen(comment->value);
00051 comment_size = (comment_len + 7) & ~7;
00052
00053 sox->header_size = SOX_FIXED_HDR + comment_size;
00054
00055 if (enc->codec_id == CODEC_ID_PCM_S32LE) {
00056 put_tag(pb, ".SoX");
00057 put_le32(pb, sox->header_size);
00058 put_le64(pb, 0);
00059 put_le64(pb, av_dbl2int(enc->sample_rate));
00060 put_le32(pb, enc->channels);
00061 put_le32(pb, comment_size);
00062 } else if (enc->codec_id == CODEC_ID_PCM_S32BE) {
00063 put_tag(pb, "XoS.");
00064 put_be32(pb, sox->header_size);
00065 put_be64(pb, 0);
00066 put_be64(pb, av_dbl2int(enc->sample_rate));
00067 put_be32(pb, enc->channels);
00068 put_be32(pb, comment_size);
00069 } else {
00070 av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n");
00071 return -1;
00072 }
00073
00074 if (comment_len)
00075 put_buffer(pb, comment->value, comment_len);
00076
00077 for ( ; comment_size > comment_len; comment_len++)
00078 put_byte(pb, 0);
00079
00080 put_flush_packet(pb);
00081
00082 return 0;
00083 }
00084
00085 static int sox_write_packet(AVFormatContext *s, AVPacket *pkt)
00086 {
00087 ByteIOContext *pb = s->pb;
00088 put_buffer(pb, pkt->data, pkt->size);
00089 return 0;
00090 }
00091
00092 static int sox_write_trailer(AVFormatContext *s)
00093 {
00094 SoXContext *sox = s->priv_data;
00095 ByteIOContext *pb = s->pb;
00096 AVCodecContext *enc = s->streams[0]->codec;
00097
00098 if (!url_is_streamed(s->pb)) {
00099
00100 int64_t file_size = url_ftell(pb);
00101 int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL;
00102 url_fseek(pb, 8, SEEK_SET);
00103 if (enc->codec_id == CODEC_ID_PCM_S32LE) {
00104 put_le64(pb, num_samples);
00105 } else
00106 put_be64(pb, num_samples);
00107 url_fseek(pb, file_size, SEEK_SET);
00108
00109 put_flush_packet(pb);
00110 }
00111
00112 return 0;
00113 }
00114
00115 AVOutputFormat sox_muxer = {
00116 "sox",
00117 NULL_IF_CONFIG_SMALL("SoX native format"),
00118 NULL,
00119 "sox",
00120 sizeof(SoXContext),
00121 CODEC_ID_PCM_S32LE,
00122 CODEC_ID_NONE,
00123 sox_write_header,
00124 sox_write_packet,
00125 sox_write_trailer,
00126 };