]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/pp_bnk.c
avformat: Constify all muxer/demuxers
[ffmpeg] / libavformat / pp_bnk.c
index 8364de1fd9c66ddae67cd5b43f1f73866a4f7da1..9455a575b7359a93e02dabf0df3ff1f422cf4315 100644 (file)
@@ -55,6 +55,7 @@ typedef struct PPBnkCtx {
     int             track_count;
     PPBnkCtxTrack   *tracks;
     uint32_t        current_track;
+    int             is_music;
 } PPBnkCtx;
 
 enum {
@@ -194,8 +195,12 @@ static int pp_bnk_read_header(AVFormatContext *s)
         goto fail;
     }
 
+    ctx->is_music = (hdr.flags & PP_BNK_FLAG_MUSIC) &&
+                    (ctx->track_count == 2) &&
+                    (ctx->tracks[0].data_size == ctx->tracks[1].data_size);
+
     /* Build the streams. */
-    for (int i = 0; i < ctx->track_count; i++) {
+    for (int i = 0; i < (ctx->is_music ? 1 : ctx->track_count); i++) {
         if (!(st = avformat_new_stream(s, NULL))) {
             ret = AVERROR(ENOMEM);
             goto fail;
@@ -204,14 +209,21 @@ static int pp_bnk_read_header(AVFormatContext *s)
         par                         = st->codecpar;
         par->codec_type             = AVMEDIA_TYPE_AUDIO;
         par->codec_id               = AV_CODEC_ID_ADPCM_IMA_CUNNING;
-        par->format                 = AV_SAMPLE_FMT_S16;
-        par->channel_layout         = AV_CH_LAYOUT_MONO;
-        par->channels               = 1;
+        par->format                 = AV_SAMPLE_FMT_S16P;
+
+        if (ctx->is_music) {
+            par->channel_layout     = AV_CH_LAYOUT_STEREO;
+            par->channels           = 2;
+        } else {
+            par->channel_layout     = AV_CH_LAYOUT_MONO;
+            par->channels           = 1;
+        }
+
         par->sample_rate            = hdr.sample_rate;
         par->bits_per_coded_sample  = 4;
         par->bits_per_raw_sample    = 16;
         par->block_align            = 1;
-        par->bit_rate               = par->sample_rate * par->bits_per_coded_sample;
+        par->bit_rate               = par->sample_rate * par->bits_per_coded_sample * par->channels;
 
         avpriv_set_pts_info(st, 64, 1, par->sample_rate);
         st->start_time              = 0;
@@ -253,18 +265,38 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt)
 
         size = FFMIN(trk->data_size - trk->bytes_read, PP_BNK_MAX_READ_SIZE);
 
-        if ((ret = av_get_packet(s->pb, pkt, size)) == AVERROR_EOF) {
-            /* If we've hit EOF, don't attempt this track again. */
-            trk->data_size = trk->bytes_read;
-            continue;
-        } else if (ret < 0) {
-            return ret;
+        if (!ctx->is_music) {
+            ret = av_get_packet(s->pb, pkt, size);
+            if (ret == AVERROR_EOF) {
+                /* If we've hit EOF, don't attempt this track again. */
+                trk->data_size = trk->bytes_read;
+                continue;
+            }
+        } else {
+            if (!pkt->data && (ret = av_new_packet(pkt, size * 2)) < 0)
+                return ret;
+            ret = avio_read(s->pb, pkt->data + size * ctx->current_track, size);
+            if (ret >= 0 && ret != size) {
+                /* Only return stereo packets if both tracks could be read. */
+                ret = AVERROR_EOF;
+            }
         }
+        if (ret < 0)
+            return ret;
 
         trk->bytes_read    += ret;
         pkt->flags         &= ~AV_PKT_FLAG_CORRUPT;
-        pkt->stream_index   = ctx->current_track++;
+        pkt->stream_index   = ctx->current_track;
         pkt->duration       = ret * 2;
+
+        if (ctx->is_music) {
+            if (pkt->stream_index == 0)
+                continue;
+
+            pkt->stream_index = 0;
+        }
+
+        ctx->current_track++;
         return 0;
     }
 
@@ -281,12 +313,32 @@ static int pp_bnk_read_close(AVFormatContext *s)
     return 0;
 }
 
-AVInputFormat ff_pp_bnk_demuxer = {
+static int pp_bnk_seek(AVFormatContext *s, int stream_index,
+                       int64_t pts, int flags)
+{
+    PPBnkCtx *ctx = s->priv_data;
+
+    if (pts != 0)
+        return AVERROR(EINVAL);
+
+    if (ctx->is_music) {
+        av_assert0(stream_index == 0);
+        ctx->tracks[0].bytes_read = 0;
+        ctx->tracks[1].bytes_read = 0;
+    } else {
+        ctx->tracks[stream_index].bytes_read = 0;
+    }
+
+    return 0;
+}
+
+const AVInputFormat ff_pp_bnk_demuxer = {
     .name           = "pp_bnk",
     .long_name      = NULL_IF_CONFIG_SMALL("Pro Pinball Series Soundbank"),
     .priv_data_size = sizeof(PPBnkCtx),
     .read_probe     = pp_bnk_probe,
     .read_header    = pp_bnk_read_header,
     .read_packet    = pp_bnk_read_packet,
-    .read_close     = pp_bnk_read_close
+    .read_close     = pp_bnk_read_close,
+    .read_seek      = pp_bnk_seek,
 };