From patchwork Wed Feb 27 23:12:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aidan Richmond X-Patchwork-Id: 12167 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id BDF57448CA6 for ; Thu, 28 Feb 2019 01:12:17 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9E10E689D42; Thu, 28 Feb 2019 01:12:17 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from EUR01-HE1-obe.outbound.protection.outlook.com (mail-oln040092065012.outbound.protection.outlook.com [40.92.65.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1E7AD680887 for ; Thu, 28 Feb 2019 01:12:10 +0200 (EET) Received: from DB5EUR01FT043.eop-EUR01.prod.protection.outlook.com (10.152.4.56) by DB5EUR01HT041.eop-EUR01.prod.protection.outlook.com (10.152.5.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1643.21; Wed, 27 Feb 2019 23:12:08 +0000 Received: from AM4PR1001MB1346.EURPRD10.PROD.OUTLOOK.COM (10.152.4.56) by DB5EUR01FT043.mail.protection.outlook.com (10.152.5.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1643.21 via Frontend Transport; Wed, 27 Feb 2019 23:12:08 +0000 Received: from AM4PR1001MB1346.EURPRD10.PROD.OUTLOOK.COM ([fe80::3c93:8abb:1405:c52a]) by AM4PR1001MB1346.EURPRD10.PROD.OUTLOOK.COM ([fe80::3c93:8abb:1405:c52a%5]) with mapi id 15.20.1643.022; Wed, 27 Feb 2019 23:12:08 +0000 From: Aidan R To: "ffmpeg-devel@ffmpeg.org" Thread-Topic: [PATCH] avformat/westwood_aud: Adds PCM format demux. Thread-Index: AQHUzvHcKyUZ+OnT3UGK1vQXI7kaaQ== Date: Wed, 27 Feb 2019 23:12:08 +0000 Message-ID: Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: DB6PR06CA0018.eurprd06.prod.outlook.com (2603:10a6:6:1::31) To AM4PR1001MB1346.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:200:99::7) x-incomingtopheadermarker: OriginalChecksum:9760389D15D34B0F41C53481C9FAF70964F57C05B027134ED5EFC037FFB4CDE4; UpperCasedChecksum:7E21C79EFED6C3071A5D04D9DCAE7C9BECADA73FC60C20030F01BF47E43D6576; SizeAsReceived:8257; Count:62 x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 2.16.1.windows.1 x-tmn: [4D9SXGsatkv3o9N9FF4jaVZN3A4COGAP] x-microsoft-original-message-id: <20190227231105.16204-1-aidan.is@hotmail.co.uk> x-ms-publictraffictype: Email x-incomingheadercount: 62 x-eopattributedmessage: 0 x-ms-exchange-slblob-mailprops: gjx25WM8ZNVIvygFamH8oyhEISf1dPMPcynM2fJU238zqn0B07fFRbdkuFUU3XCfy0jGitzRyXWoj14h8foEj31D1yu92Oh5eKaSHFVJ25ma6JXAC+j7/U9sjXLddmJvNzFZ+q4rUHR1dV2/2bFgbiE4nmXSLQsGMOyEQgU68j2lKkbbidrG1Qjh9bJUxqh253t4LGlEd/uinLcJocKw7pfmCk+hrj8ZCyM3zj1rMdBebv/+qPd6ROxfKzJYxMmjghy8s47U/ekwxml715J6Y6V0hweuV1la1Q8e9K6x4hJHR+KuROqqSNKr7LimVo0QfU8/q7nB6ldUxaMik93ejaNsatxxUJfaPil24YAcTlXxO3gdTSBj5kWmN1Yi2jfRe/Z2goiREkfspWFtnmr72J4dO2VcR6rGMsdprHExvTHdGvT/dX1POWN9RF0SHLaLzDj/Dlmc9A3liYRubfe/BPT9NYTxDvm3v/Jma1fYoOSEqnRGvpTOVw8Z1bJ4Jxw5hJFYo6JOdYSpFxP607qkfcXt1Tpb0OtO2QgxovjkB5jCA+yOioUDRhwHscmw+FImzgZFmoGlR3oVJadYhEhn5YzXweLTVTWIf4/tSi1jyKCWsp06EnyhKmHUKrMTzfVL5bpzEJ6BlbW/bObsKhNbqHlPHcyIspnlvP6e0f/2n388qeV+tq7VXWHl3HIcifWQU0pS/TScGpuTrSY1IfiYfKcnqnFdoYYHCh7ZIbWJVHc= x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(201702061078)(5061506573)(5061507331)(1603103135)(2017031320274)(2017031322404)(201702181274)(2017031323274)(2017031324274)(1601125500)(1603101475)(1701031045); SRVR:DB5EUR01HT041; x-ms-traffictypediagnostic: DB5EUR01HT041: x-microsoft-antispam-message-info: EGQyKXwPrES81ah7/gYnxCfgFLkfhWEpy0WJvadiXk2UwbKEFqCbWFwPA428r6mE MIME-Version: 1.0 X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 3412d8b0-16d7-4f23-8d8b-08d69d08feac X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-originalarrivaltime: 27 Feb 2019 23:12:07.6153 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB5EUR01HT041 Subject: [FFmpeg-devel] [PATCH] avformat/westwood_aud: Adds PCM format demux. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Aidan R Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" PCM format AUD files are found in Westwood's Blade Runner game. --- libavformat/westwood_aud.c | 80 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 9c2d35cb8a..5d7e827bc1 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -41,6 +41,12 @@ #define AUD_HEADER_SIZE 12 #define AUD_CHUNK_PREAMBLE_SIZE 8 #define AUD_CHUNK_SIGNATURE 0x0000DEAF +#define AUD_PCM_CHUNK_SIZE 2048 /* arbitrary size to pull out of PCM data*/ + +typedef struct AUDDemuxContext { + int size; + int pos; +} AUDDemuxContext; static int wsaud_probe(AVProbeData *p) { @@ -50,10 +56,10 @@ static int wsaud_probe(AVProbeData *p) * so perform sanity checks on various header parameters: * 8000 <= sample rate (16 bits) <= 48000 ==> 40001 acceptable numbers * flags <= 0x03 (2 LSBs are used) ==> 4 acceptable numbers - * compression type (8 bits) = 1 or 99 ==> 2 acceptable numbers + * compression type (8 bits) = 0, 1 or 99 ==> 3 acceptable numbers * first audio chunk signature (32 bits) ==> 1 acceptable number - * The number space contains 2^64 numbers. There are 40001 * 4 * 2 * 1 = - * 320008 acceptable number combinations. + * The number space contains 2^64 numbers. There are 40001 * 4 * 3 * 1 = + * 480012 acceptable number combinations. */ if (p->buf_size < AUD_HEADER_SIZE + AUD_CHUNK_PREAMBLE_SIZE) @@ -69,13 +75,22 @@ static int wsaud_probe(AVProbeData *p) if (p->buf[10] & 0xFC) return 0; - if (p->buf[11] != 99 && p->buf[11] != 1) + /* valid format values are 99 == adpcm, 1 == snd1 and 0 == pcm */ + if (p->buf[11] != 99 && p->buf[11] != 1 && p->buf[11] != 0) return 0; - /* read ahead to the first audio chunk and validate the first header signature */ - if (AV_RL32(&p->buf[16]) != AUD_CHUNK_SIGNATURE) + /* read ahead to the first audio chunk and validate the first header + * signature pcm format does not use a chunk format, so don't check + * for that codec */ + if (p->buf[11] != 0 && AV_RL32(&p->buf[16]) != AUD_CHUNK_SIGNATURE) return 0; + /* if we have pcm format then compressed size should equal + * uncompressed size */ + if (p->buf[11] == 0 && AV_RL32(&p->buf[2]) != AV_RL32(&p->buf[6])) { + return 0; + } + /* return 1/2 certainty since this file check is a little sketchy */ return AVPROBE_SCORE_EXTENSION; } @@ -83,16 +98,20 @@ static int wsaud_probe(AVProbeData *p) static int wsaud_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; + AUDDemuxContext *aud = s->priv_data; AVStream *st; unsigned char header[AUD_HEADER_SIZE]; - int sample_rate, channels, codec; + int sample_rate, channels, codec, bits_per_sample; if (avio_read(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE) return AVERROR(EIO); sample_rate = AV_RL16(&header[0]); channels = (header[10] & 0x1) + 1; + bits_per_sample = (header[10] & 0x2) ? 16 : 8; codec = header[11]; + aud->size = AV_RL32(&header[2]); + aud->pos = 0; /* used to track position in a PCM stream */ /* initialize the audio decoder stream */ st = avformat_new_stream(s, NULL); @@ -100,6 +119,15 @@ static int wsaud_read_header(AVFormatContext *s) return AVERROR(ENOMEM); switch (codec) { + case 0: + if (bits_per_sample == 8) { + st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; + } else { + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + } + st->codecpar->bits_per_coded_sample = bits_per_sample; + st->codecpar->bit_rate = channels * sample_rate * bits_per_sample; + break; case 1: if (channels != 1) { avpriv_request_sample(s, "Stereo WS-SND1"); @@ -130,20 +158,24 @@ static int wsaud_read_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; + AUDDemuxContext *aud = s->priv_data; unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE]; - unsigned int chunk_size; + unsigned int chunk_size, bytes_per_sample; int ret = 0; AVStream *st = s->streams[0]; - if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) != - AUD_CHUNK_PREAMBLE_SIZE) - return AVERROR(EIO); + /* AUD files don't store PCM audio in chunks */ + if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE) { + if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) != + AUD_CHUNK_PREAMBLE_SIZE) + return AVERROR(EIO); - /* validate the chunk */ - if (AV_RL32(&preamble[4]) != AUD_CHUNK_SIGNATURE) - return AVERROR_INVALIDDATA; + /* validate the chunk */ + if (AV_RL32(&preamble[4]) != AUD_CHUNK_SIGNATURE) + return AVERROR_INVALIDDATA; - chunk_size = AV_RL16(&preamble[0]); + chunk_size = AV_RL16(&preamble[0]); + } if (st->codecpar->codec_id == AV_CODEC_ID_WESTWOOD_SND1) { /* For Westwood SND1 audio we need to add the output size and input @@ -159,7 +191,7 @@ static int wsaud_read_packet(AVFormatContext *s, AV_WL16(&pkt->data[2], chunk_size); pkt->duration = out_size; - } else { + } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WS) { ret = av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR(EIO); @@ -172,7 +204,20 @@ static int wsaud_read_packet(AVFormatContext *s, /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ pkt->duration = (chunk_size * 2) / st->codecpar->channels; - } + } else { + chunk_size = FFMIN(aud->size - aud->pos, AUD_PCM_CHUNK_SIZE); + if(chunk_size <= 0) + return AVERROR_EOF; + + aud->pos += chunk_size; + ret = av_get_packet(pb, pkt, chunk_size); + if (ret != chunk_size) + return AVERROR(EIO); + + bytes_per_sample = st->codecpar->bits_per_coded_sample / 8; + pkt->duration = (chunk_size / bytes_per_sample) / + st->codecpar->channels; + } pkt->stream_index = st->index; return ret; @@ -181,6 +226,7 @@ static int wsaud_read_packet(AVFormatContext *s, AVInputFormat ff_wsaud_demuxer = { .name = "wsaud", .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio"), + .priv_data_size = sizeof(AUDDemuxContext), .read_probe = wsaud_probe, .read_header = wsaud_read_header, .read_packet = wsaud_read_packet,