]> git.sesse.net Git - ffmpeg/blob - libavformat/omaenc.c
Merge commit '271ce76d317c5432e151216cf23f12b77ed6cb7e'
[ffmpeg] / libavformat / omaenc.c
1 /*
2  * Sony OpenMG (OMA) muxer
3  *
4  * Copyright (c) 2011 Michael Karcher
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "avformat.h"
24 #include "avio_internal.h"
25 #include "id3v2.h"
26 #include "internal.h"
27 #include "oma.h"
28 #include "rawenc.h"
29
30 static av_cold int oma_write_header(AVFormatContext *s)
31 {
32     int i;
33     AVCodecContext *format;
34     int srate_index;
35     int isjointstereo;
36
37     format = s->streams[0]->codec;
38     /* check for support of the format first */
39
40     for (srate_index = 0; ; srate_index++) {
41         if (ff_oma_srate_tab[srate_index] == 0) {
42             av_log(s, AV_LOG_ERROR, "Sample rate %d not supported in OpenMG audio\n",
43                    format->sample_rate);
44             return AVERROR(EINVAL);
45         }
46
47         if (ff_oma_srate_tab[srate_index] * 100 == format->sample_rate)
48             break;
49     }
50
51     /* Metadata; OpenMG does not support ID3v2.4 */
52     ff_id3v2_write_simple(s, 3, ID3v2_EA3_MAGIC);
53
54     ffio_wfourcc(s->pb, "EA3\0");
55     avio_w8(s->pb, EA3_HEADER_SIZE >> 7);
56     avio_w8(s->pb, EA3_HEADER_SIZE & 0x7F);
57     avio_wl16(s->pb, 0xFFFF);       /* not encrypted */
58     for (i = 0; i < 6; i++)
59         avio_wl32(s->pb, 0);        /* Padding + DRM id */
60
61     switch(format->codec_tag) {
62     case OMA_CODECID_ATRAC3:
63         if (format->channels != 2) {
64             av_log(s, AV_LOG_ERROR, "ATRAC3 in OMA is only supported with 2 channels\n");
65             return AVERROR(EINVAL);
66         }
67         if (format->extradata_size == 14) /* WAV format extradata */
68             isjointstereo = format->extradata[6] != 0;
69         else if(format->extradata_size == 10) /* RM format extradata */
70             isjointstereo = format->extradata[8] == 0x12;
71         else {
72             av_log(s, AV_LOG_ERROR, "ATRAC3: Unsupported extradata size\n");
73             return AVERROR(EINVAL);
74         }
75         avio_wb32(s->pb, (OMA_CODECID_ATRAC3 << 24) |
76                          (isjointstereo << 17) |
77                          (srate_index << 13) |
78                          (format->block_align/8));
79         break;
80     case OMA_CODECID_ATRAC3P:
81         avio_wb32(s->pb, (OMA_CODECID_ATRAC3P << 24) |
82                          (srate_index << 13) |
83                          (format->channels << 10) |
84                          (format->block_align/8 - 1));
85         break;
86     default:
87         av_log(s, AV_LOG_ERROR, "unsupported codec tag %d for write\n",
88                format->codec_tag);
89         return AVERROR(EINVAL);
90     }
91     for (i = 0; i < (EA3_HEADER_SIZE - 36)/4; i++)
92         avio_wl32(s->pb, 0);        /* Padding */
93
94     return 0;
95 }
96
97 AVOutputFormat ff_oma_muxer = {
98     .name              = "oma",
99     .long_name         = NULL_IF_CONFIG_SMALL("Sony OpenMG audio"),
100     .mime_type         = "audio/x-oma",
101     .extensions        = "oma",
102     .audio_codec       = AV_CODEC_ID_ATRAC3,
103     .write_header      = oma_write_header,
104     .write_packet      = ff_raw_write_packet,
105     .codec_tag         = (const AVCodecTag* const []){ff_oma_codec_tags, 0},
106     .flags             = AVFMT_NOTIMESTAMPS,
107 };