1/* 2 * True Audio (TTA) muxer 3 * Copyright (c) 2016 James Almer 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "libavutil/crc.h" 23#include "libavutil/intreadwrite.h" 24 25#include "libavcodec/packet_internal.h" 26#include "apetag.h" 27#include "avformat.h" 28#include "avio_internal.h" 29#include "internal.h" 30 31typedef struct TTAMuxContext { 32 AVIOContext *seek_table; 33 PacketList queue; 34 uint32_t nb_samples; 35 int frame_size; 36 int last_frame; 37} TTAMuxContext; 38 39static int tta_init(AVFormatContext *s) 40{ 41 TTAMuxContext *tta = s->priv_data; 42 AVCodecParameters *par; 43 44 if (s->nb_streams != 1) { 45 av_log(s, AV_LOG_ERROR, "Only one stream is supported\n"); 46 return AVERROR(EINVAL); 47 } 48 par = s->streams[0]->codecpar; 49 50 if (par->codec_id != AV_CODEC_ID_TTA) { 51 av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); 52 return AVERROR(EINVAL); 53 } 54 if (par->extradata && par->extradata_size < 22) { 55 av_log(s, AV_LOG_ERROR, "Invalid TTA extradata\n"); 56 return AVERROR_INVALIDDATA; 57 } 58 59 /* Prevent overflow */ 60 if (par->sample_rate > 0x7FFFFFu) { 61 av_log(s, AV_LOG_ERROR, "Sample rate too large\n"); 62 return AVERROR(EINVAL); 63 } 64 tta->frame_size = par->sample_rate * 256 / 245; 65 avpriv_set_pts_info(s->streams[0], 64, 1, par->sample_rate); 66 67 return 0; 68} 69 70static int tta_write_header(AVFormatContext *s) 71{ 72 TTAMuxContext *tta = s->priv_data; 73 AVCodecParameters *par = s->streams[0]->codecpar; 74 int ret; 75 76 if ((ret = avio_open_dyn_buf(&tta->seek_table)) < 0) 77 return ret; 78 79 /* Ignore most extradata information if present. It can be innacurate 80 if for example remuxing from Matroska */ 81 ffio_init_checksum(s->pb, ff_crcEDB88320_update, UINT32_MAX); 82 ffio_init_checksum(tta->seek_table, ff_crcEDB88320_update, UINT32_MAX); 83 avio_write(s->pb, "TTA1", 4); 84 avio_wl16(s->pb, par->extradata ? AV_RL16(par->extradata + 4) : 1); 85 avio_wl16(s->pb, par->ch_layout.nb_channels); 86 avio_wl16(s->pb, par->bits_per_raw_sample); 87 avio_wl32(s->pb, par->sample_rate); 88 89 return 0; 90} 91 92static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) 93{ 94 TTAMuxContext *tta = s->priv_data; 95 int ret; 96 97 ret = avpriv_packet_list_put(&tta->queue, pkt, NULL, 0); 98 if (ret < 0) { 99 return ret; 100 } 101 pkt = &tta->queue.tail->pkt; 102 103 avio_wl32(tta->seek_table, pkt->size); 104 tta->nb_samples += pkt->duration; 105 106 if (tta->frame_size != pkt->duration) { 107 if (tta->last_frame) { 108 /* Two frames with a different duration than the default frame 109 size means the TTA stream comes from a faulty container, and 110 there's no way the last frame duration will be correct. */ 111 av_log(s, AV_LOG_ERROR, "Invalid frame durations\n"); 112 113 return AVERROR_INVALIDDATA; 114 } 115 /* First frame with a different duration than the default frame size. 116 Assume it's the last frame in the stream and continue. */ 117 tta->last_frame++; 118 } 119 120 return 0; 121} 122 123static void tta_queue_flush(AVFormatContext *s) 124{ 125 TTAMuxContext *tta = s->priv_data; 126 AVPacket *const pkt = ffformatcontext(s)->pkt; 127 128 while (tta->queue.head) { 129 avpriv_packet_list_get(&tta->queue, pkt); 130 avio_write(s->pb, pkt->data, pkt->size); 131 av_packet_unref(pkt); 132 } 133} 134 135static int tta_write_trailer(AVFormatContext *s) 136{ 137 TTAMuxContext *tta = s->priv_data; 138 uint8_t *ptr; 139 unsigned int crc; 140 int size; 141 142 avio_wl32(s->pb, tta->nb_samples); 143 crc = ffio_get_checksum(s->pb) ^ UINT32_MAX; 144 avio_wl32(s->pb, crc); 145 146 /* Write Seek table */ 147 crc = ffio_get_checksum(tta->seek_table) ^ UINT32_MAX; 148 avio_wl32(tta->seek_table, crc); 149 size = avio_get_dyn_buf(tta->seek_table, &ptr); 150 avio_write(s->pb, ptr, size); 151 152 /* Write audio data */ 153 tta_queue_flush(s); 154 155 ff_ape_write_tag(s); 156 157 return 0; 158} 159 160static void tta_deinit(AVFormatContext *s) 161{ 162 TTAMuxContext *tta = s->priv_data; 163 164 ffio_free_dyn_buf(&tta->seek_table); 165 avpriv_packet_list_free(&tta->queue); 166} 167 168const AVOutputFormat ff_tta_muxer = { 169 .name = "tta", 170 .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), 171 .mime_type = "audio/x-tta", 172 .extensions = "tta", 173 .priv_data_size = sizeof(TTAMuxContext), 174 .audio_codec = AV_CODEC_ID_TTA, 175 .video_codec = AV_CODEC_ID_NONE, 176 .init = tta_init, 177 .deinit = tta_deinit, 178 .write_header = tta_write_header, 179 .write_packet = tta_write_packet, 180 .write_trailer = tta_write_trailer, 181}; 182