1/* 2 * Digital Speech Standard (DSS) demuxer 3 * Copyright (c) 2014 Oleksij Rempel <linux@rempel-privat.de> 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/channel_layout.h" 23#include "libavutil/intreadwrite.h" 24 25#include "avformat.h" 26#include "internal.h" 27 28#define DSS_HEAD_OFFSET_AUTHOR 0xc 29#define DSS_AUTHOR_SIZE 16 30 31#define DSS_HEAD_OFFSET_START_TIME 0x26 32#define DSS_HEAD_OFFSET_END_TIME 0x32 33#define DSS_TIME_SIZE 12 34 35#define DSS_HEAD_OFFSET_ACODEC 0x2a4 36#define DSS_ACODEC_DSS_SP 0x0 /* SP mode */ 37#define DSS_ACODEC_G723_1 0x2 /* LP mode */ 38 39#define DSS_HEAD_OFFSET_COMMENT 0x31e 40#define DSS_COMMENT_SIZE 64 41 42#define DSS_BLOCK_SIZE 512 43#define DSS_AUDIO_BLOCK_HEADER_SIZE 6 44#define DSS_FRAME_SIZE 42 45 46static const uint8_t frame_size[4] = { 24, 20, 4, 1 }; 47 48typedef struct DSSDemuxContext { 49 unsigned int audio_codec; 50 int counter; 51 int swap; 52 int dss_sp_swap_byte; 53 54 int packet_size; 55 int dss_header_size; 56} DSSDemuxContext; 57 58static int dss_probe(const AVProbeData *p) 59{ 60 if ( AV_RL32(p->buf) != MKTAG(0x2, 'd', 's', 's') 61 && AV_RL32(p->buf) != MKTAG(0x3, 'd', 's', 's')) 62 return 0; 63 64 return AVPROBE_SCORE_MAX; 65} 66 67static int dss_read_metadata_date(AVFormatContext *s, unsigned int offset, 68 const char *key) 69{ 70 AVIOContext *pb = s->pb; 71 char datetime[64], string[DSS_TIME_SIZE + 1] = { 0 }; 72 int y, month, d, h, minute, sec; 73 int ret; 74 75 avio_seek(pb, offset, SEEK_SET); 76 77 ret = avio_read(s->pb, string, DSS_TIME_SIZE); 78 if (ret < DSS_TIME_SIZE) 79 return ret < 0 ? ret : AVERROR_EOF; 80 81 if (sscanf(string, "%2d%2d%2d%2d%2d%2d", &y, &month, &d, &h, &minute, &sec) != 6) 82 return AVERROR_INVALIDDATA; 83 /* We deal with a two-digit year here, so set the default date to 2000 84 * and hope it will never be used in the next century. */ 85 snprintf(datetime, sizeof(datetime), "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", 86 y + 2000, month, d, h, minute, sec); 87 return av_dict_set(&s->metadata, key, datetime, 0); 88} 89 90static int dss_read_metadata_string(AVFormatContext *s, unsigned int offset, 91 unsigned int size, const char *key) 92{ 93 AVIOContext *pb = s->pb; 94 char *value; 95 int ret; 96 97 avio_seek(pb, offset, SEEK_SET); 98 99 value = av_mallocz(size + 1); 100 if (!value) 101 return AVERROR(ENOMEM); 102 103 ret = avio_read(s->pb, value, size); 104 if (ret < size) { 105 av_free(value); 106 return ret < 0 ? ret : AVERROR_EOF; 107 } 108 109 return av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); 110} 111 112static int dss_read_header(AVFormatContext *s) 113{ 114 DSSDemuxContext *ctx = s->priv_data; 115 AVIOContext *pb = s->pb; 116 AVStream *st; 117 int ret, version; 118 119 st = avformat_new_stream(s, NULL); 120 if (!st) 121 return AVERROR(ENOMEM); 122 123 version = avio_r8(pb); 124 ctx->dss_header_size = version * DSS_BLOCK_SIZE; 125 126 ret = dss_read_metadata_string(s, DSS_HEAD_OFFSET_AUTHOR, 127 DSS_AUTHOR_SIZE, "author"); 128 if (ret) 129 return ret; 130 131 ret = dss_read_metadata_date(s, DSS_HEAD_OFFSET_END_TIME, "date"); 132 if (ret) 133 return ret; 134 135 ret = dss_read_metadata_string(s, DSS_HEAD_OFFSET_COMMENT, 136 DSS_COMMENT_SIZE, "comment"); 137 if (ret) 138 return ret; 139 140 avio_seek(pb, DSS_HEAD_OFFSET_ACODEC, SEEK_SET); 141 ctx->audio_codec = avio_r8(pb); 142 143 if (ctx->audio_codec == DSS_ACODEC_DSS_SP) { 144 st->codecpar->codec_id = AV_CODEC_ID_DSS_SP; 145 st->codecpar->sample_rate = 11025; 146 s->bit_rate = 8 * (DSS_FRAME_SIZE - 1) * st->codecpar->sample_rate 147 * 512 / (506 * 264); 148 } else if (ctx->audio_codec == DSS_ACODEC_G723_1) { 149 st->codecpar->codec_id = AV_CODEC_ID_G723_1; 150 st->codecpar->sample_rate = 8000; 151 } else { 152 avpriv_request_sample(s, "Support for codec %x in DSS", 153 ctx->audio_codec); 154 return AVERROR_PATCHWELCOME; 155 } 156 157 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 158 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; 159 160 avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 161 st->start_time = 0; 162 163 /* Jump over header */ 164 165 if (avio_seek(pb, ctx->dss_header_size, SEEK_SET) != ctx->dss_header_size) 166 return AVERROR(EIO); 167 168 ctx->counter = 0; 169 ctx->swap = 0; 170 171 return 0; 172} 173 174static void dss_skip_audio_header(AVFormatContext *s, AVPacket *pkt) 175{ 176 DSSDemuxContext *ctx = s->priv_data; 177 AVIOContext *pb = s->pb; 178 179 avio_skip(pb, DSS_AUDIO_BLOCK_HEADER_SIZE); 180 ctx->counter += DSS_BLOCK_SIZE - DSS_AUDIO_BLOCK_HEADER_SIZE; 181} 182 183static void dss_sp_byte_swap(DSSDemuxContext *ctx, uint8_t *data) 184{ 185 int i; 186 187 if (ctx->swap) { 188 for (i = 0; i < DSS_FRAME_SIZE - 2; i += 2) 189 data[i] = data[i + 4]; 190 191 /* Zero the padding. */ 192 data[DSS_FRAME_SIZE] = 0; 193 data[1] = ctx->dss_sp_swap_byte; 194 } else { 195 ctx->dss_sp_swap_byte = data[DSS_FRAME_SIZE - 2]; 196 } 197 198 /* make sure byte 40 is always 0 */ 199 data[DSS_FRAME_SIZE - 2] = 0; 200 ctx->swap ^= 1; 201} 202 203static int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt) 204{ 205 DSSDemuxContext *ctx = s->priv_data; 206 int read_size, ret, offset = 0, buff_offset = 0; 207 int64_t pos = avio_tell(s->pb); 208 209 if (ctx->counter == 0) 210 dss_skip_audio_header(s, pkt); 211 212 if (ctx->swap) { 213 read_size = DSS_FRAME_SIZE - 2; 214 buff_offset = 3; 215 } else 216 read_size = DSS_FRAME_SIZE; 217 218 ret = av_new_packet(pkt, DSS_FRAME_SIZE); 219 if (ret < 0) 220 return ret; 221 222 pkt->duration = 264; 223 pkt->pos = pos; 224 pkt->stream_index = 0; 225 226 if (ctx->counter < read_size) { 227 ret = avio_read(s->pb, pkt->data + buff_offset, 228 ctx->counter); 229 if (ret < ctx->counter) 230 goto error_eof; 231 232 offset = ctx->counter; 233 dss_skip_audio_header(s, pkt); 234 } 235 ctx->counter -= read_size; 236 237 /* This will write one byte into pkt's padding if buff_offset == 3 */ 238 ret = avio_read(s->pb, pkt->data + offset + buff_offset, 239 read_size - offset); 240 if (ret < read_size - offset) 241 goto error_eof; 242 243 dss_sp_byte_swap(ctx, pkt->data); 244 245 if (ctx->dss_sp_swap_byte < 0) { 246 return AVERROR(EAGAIN); 247 } 248 249 return 0; 250 251error_eof: 252 return ret < 0 ? ret : AVERROR_EOF; 253} 254 255static int dss_723_1_read_packet(AVFormatContext *s, AVPacket *pkt) 256{ 257 DSSDemuxContext *ctx = s->priv_data; 258 AVStream *st = s->streams[0]; 259 int size, byte, ret, offset; 260 int64_t pos = avio_tell(s->pb); 261 262 if (ctx->counter == 0) 263 dss_skip_audio_header(s, pkt); 264 265 /* We make one byte-step here. Don't forget to add offset. */ 266 byte = avio_r8(s->pb); 267 if (byte == 0xff) 268 return AVERROR_INVALIDDATA; 269 270 size = frame_size[byte & 3]; 271 272 ctx->packet_size = size; 273 ctx->counter--; 274 275 ret = av_new_packet(pkt, size); 276 if (ret < 0) 277 return ret; 278 pkt->pos = pos; 279 280 pkt->data[0] = byte; 281 offset = 1; 282 pkt->duration = 240; 283 s->bit_rate = 8LL * size-- * st->codecpar->sample_rate * 512 / (506 * pkt->duration); 284 285 pkt->stream_index = 0; 286 287 if (ctx->counter < size) { 288 ret = avio_read(s->pb, pkt->data + offset, 289 ctx->counter); 290 if (ret < ctx->counter) 291 return ret < 0 ? ret : AVERROR_EOF; 292 293 offset += ctx->counter; 294 size -= ctx->counter; 295 ctx->counter = 0; 296 dss_skip_audio_header(s, pkt); 297 } 298 ctx->counter -= size; 299 300 ret = avio_read(s->pb, pkt->data + offset, size); 301 if (ret < size) 302 return ret < 0 ? ret : AVERROR_EOF; 303 304 return 0; 305} 306 307static int dss_read_packet(AVFormatContext *s, AVPacket *pkt) 308{ 309 DSSDemuxContext *ctx = s->priv_data; 310 311 if (ctx->audio_codec == DSS_ACODEC_DSS_SP) 312 return dss_sp_read_packet(s, pkt); 313 else 314 return dss_723_1_read_packet(s, pkt); 315} 316 317static int dss_read_seek(AVFormatContext *s, int stream_index, 318 int64_t timestamp, int flags) 319{ 320 DSSDemuxContext *ctx = s->priv_data; 321 int64_t ret, seekto; 322 uint8_t header[DSS_AUDIO_BLOCK_HEADER_SIZE]; 323 int offset; 324 325 if (ctx->audio_codec == DSS_ACODEC_DSS_SP) 326 seekto = timestamp / 264 * 41 / 506 * 512; 327 else 328 seekto = timestamp / 240 * ctx->packet_size / 506 * 512; 329 330 if (seekto < 0) 331 seekto = 0; 332 333 seekto += ctx->dss_header_size; 334 335 ret = avio_seek(s->pb, seekto, SEEK_SET); 336 if (ret < 0) 337 return ret; 338 339 avio_read(s->pb, header, DSS_AUDIO_BLOCK_HEADER_SIZE); 340 ctx->swap = !!(header[0] & 0x80); 341 offset = 2*header[1] + 2*ctx->swap; 342 if (offset < DSS_AUDIO_BLOCK_HEADER_SIZE) 343 return AVERROR_INVALIDDATA; 344 if (offset == DSS_AUDIO_BLOCK_HEADER_SIZE) { 345 ctx->counter = 0; 346 offset = avio_skip(s->pb, -DSS_AUDIO_BLOCK_HEADER_SIZE); 347 } else { 348 ctx->counter = DSS_BLOCK_SIZE - offset; 349 offset = avio_skip(s->pb, offset - DSS_AUDIO_BLOCK_HEADER_SIZE); 350 } 351 ctx->dss_sp_swap_byte = -1; 352 return 0; 353} 354 355 356const AVInputFormat ff_dss_demuxer = { 357 .name = "dss", 358 .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard (DSS)"), 359 .priv_data_size = sizeof(DSSDemuxContext), 360 .read_probe = dss_probe, 361 .read_header = dss_read_header, 362 .read_packet = dss_read_packet, 363 .read_seek = dss_read_seek, 364 .extensions = "dss" 365}; 366