diff mbox series

[FFmpeg-devel,1/2] avformat/psxstr: infer video FPS using sector LBA

Message ID PAVPR08MB9795D2C5FEDFD31CBD640AFF9A732@PAVPR08MB9795.eurprd08.prod.outlook.com
State New
Headers show
Series [FFmpeg-devel,1/2] avformat/psxstr: infer video FPS using sector LBA | expand

Checks

Context Check Description
andriy/configure_x86 warning Failed to apply patch
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

aybe aybe Jan. 16, 2024, 2:36 p.m. UTC
Signed-off-by: aybe <aybe@users.noreply.github.com>
---
  libavformat/psxstr.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
  1 file changed, 42 insertions(+), 2 deletions(-)

--
2.41.0.windows.1
diff mbox series

Patch

diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c
index 306a690f52..c718fb6daf 100644
--- a/libavformat/psxstr.c
+++ b/libavformat/psxstr.c
@@ -65,6 +65,9 @@  typedef struct StrDemuxContext {

      /* a STR file can contain up to 32 channels of data */
      StrChannel channels[32];
+
+    /* the index for the first frame (sector, LBA units)*/
+    int64_t first_frame_index;
  } StrDemuxContext;

  static const uint8_t sync_header[12] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
@@ -150,18 +153,51 @@  static int str_read_header(AVFormatContext *s)
          str->channels[i].audio_stream_index= -1;
      }

+    str->first_frame_index = 0;
+
      s->ctx_flags |= AVFMTCTX_NOHEADER;

      return 0;
  }

+static uint8_t bcd_to_dec(uint8_t bcd)
+{
+    uint8_t dec = (bcd & 0xF) + (((bcd >> 4) & 0xF) * 10);
+
+    return dec;
+}
+
+static int32_t msf_to_lba(uint8_t m, uint8_t s, uint8_t f)
+{
+    int32_t lba = 0; /* int because it can be negative! */
+
+    m = bcd_to_dec(m);
+    s = bcd_to_dec(s);
+    f = bcd_to_dec(f);
+
+    lba = (((m * 60 + s) * 75) + f) - 150;
+
+    return lba;
+}
+
+static int32_t str_get_frame_lba(uint8_t sector[2352])
+{
+    uint8_t m = sector[0xC];
+    uint8_t s = sector[0xD];
+    uint8_t f = sector[0xE];
+
+    int32_t lba = msf_to_lba(m, s, f);
+
+    return lba;
+}
+
  static int str_read_packet(AVFormatContext *s,
                             AVPacket *ret_pkt)
  {
      AVIOContext *pb = s->pb;
      StrDemuxContext *str = s->priv_data;
      unsigned char sector[RAW_CD_SECTOR_SIZE];
-    int channel, ret;
+    int channel, ret, frame_lba;
      AVPacket *pkt;
      AVStream *st;

@@ -200,10 +236,12 @@  static int str_read_packet(AVFormatContext *s,
                      st = avformat_new_stream(s, NULL);
                      if (!st)
                          return AVERROR(ENOMEM);
-                    avpriv_set_pts_info(st, 64, 1, 15);
+                    avpriv_set_pts_info(st, 64, 1, 150); /* 150 sectors at 2x speed */

                      str->channels[channel].video_stream_index = st->index;

+                    str->first_frame_index = str_get_frame_lba(sector);
+
                      st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
                      st->codecpar->codec_id   = AV_CODEC_ID_MDEC;
                      st->codecpar->codec_tag  = 0;  /* no fourcc */
@@ -223,6 +261,8 @@  static int str_read_packet(AVFormatContext *s,
                          return ret;
                      memset(pkt->data, 0, sector_count*VIDEO_DATA_CHUNK_SIZE);

+                    frame_lba = str_get_frame_lba(sector);
+                    pkt->pts = frame_lba - str->first_frame_index;
                      pkt->pos= avio_tell(pb) - RAW_CD_SECTOR_SIZE;
                      pkt->stream_index =
                          str->channels[channel].video_stream_index;