]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/smacker.c
avformat: Constify all muxer/demuxers
[ffmpeg] / libavformat / smacker.c
index 201372aee68aaf5f5dedd0ed767a9d214afae20b..a96093b191dd0cb692e16ef4554291e9c99e168b 100644 (file)
@@ -50,14 +50,15 @@ typedef struct SmackerContext {
     /* internal variables */
     int64_t next_frame_pos;
     int cur_frame;
+    int videoindex;
+    int indexes[7];
+    int duration_size[7];
     /* current frame for demuxing */
     uint32_t frame_size;
     int flags;
     int next_audio_index;
     int new_palette;
     uint8_t pal[768];
-    int indexes[7];
-    int videoindex;
     int64_t aud_pts[7];
 } SmackerContext;
 
@@ -104,8 +105,8 @@ static int smacker_read_header(AVFormatContext *s)
     height = avio_rl32(pb);
     smk->frames = avio_rl32(pb);
     pts_inc = avio_rl32(pb);
-    if (pts_inc > INT_MAX / 100) {
-        av_log(s, AV_LOG_ERROR, "pts_inc %d is too large\n", pts_inc);
+    if (pts_inc > INT_MAX / 100 || pts_inc == INT_MIN) {
+        av_log(s, AV_LOG_ERROR, "pts_inc %d is invalid\n", pts_inc);
         return AVERROR_INVALIDDATA;
     }
 
@@ -197,6 +198,8 @@ static int smacker_read_header(AVFormatContext *s)
             if (par->bits_per_coded_sample == 16 &&
                 par->codec_id == AV_CODEC_ID_PCM_U8)
                 par->codec_id = AV_CODEC_ID_PCM_S16LE;
+            else
+                smk->duration_size[i] = 4;
             avpriv_set_pts_info(ast, 64, 1, par->sample_rate * par->channels
                                             * par->bits_per_coded_sample / 8);
         }
@@ -205,10 +208,11 @@ static int smacker_read_header(AVFormatContext *s)
     avio_rl32(pb); /* padding */
 
     /* setup data */
-    smk->frm_size  = av_malloc_array(smk->frames, sizeof(*smk->frm_size) +
+    st->priv_data  = av_malloc_array(smk->frames, sizeof(*smk->frm_size) +
                                                   sizeof(*smk->frm_flags));
-    if (!smk->frm_size)
+    if (!st->priv_data)
         return AVERROR(ENOMEM);
+    smk->frm_size  = st->priv_data;
     smk->frm_flags = (void*)(smk->frm_size + smk->frames);
 
     /* read frame info */
@@ -219,14 +223,12 @@ static int smacker_read_header(AVFormatContext *s)
         /* load trees to extradata, they will be unpacked by decoder */
         (ret = ffio_read_size(pb, par->extradata + 16,
                               par->extradata_size - 16)) < 0) {
-        av_freep(&smk->frm_size);
         return ret;
     }
 
     return 0;
 }
 
-
 static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     SmackerContext *smk = s->priv_data;
@@ -243,7 +245,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
         flags = smk->frm_flags[smk->cur_frame];
         smk->flags = flags >> 1;
         /* handle palette change event */
-        if(flags & SMACKER_PAL){
+        if (flags & SMACKER_PAL) {
             int size, sz, t, off, j, pos;
             uint8_t *pal = smk->pal;
             uint8_t oldpal[768];
@@ -258,12 +260,12 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
             smk->frame_size -= size--;
             sz = 0;
             pos = avio_tell(s->pb) + size;
-            while(sz < 256){
+            while (sz < 256) {
                 t = avio_r8(s->pb);
-                if(t & 0x80){ /* skip palette entries */
-                    sz += (t & 0x7F) + 1;
+                if (t & 0x80) { /* skip palette entries */
+                    sz  +=  (t & 0x7F) + 1;
                     pal += ((t & 0x7F) + 1) * 3;
-                } else if(t & 0x40){ /* copy with offset */
+                } else if (t & 0x40) { /* copy with offset */
                     off = avio_r8(s->pb);
                     j = (t & 0x3F) + 1;
                     if (off + j > 0x100) {
@@ -274,7 +276,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
                         goto next_frame;
                     }
                     off *= 3;
-                    while(j-- && sz < 256) {
+                    while (j-- && sz < 256) {
                         *pal++ = oldpal[off + 0];
                         *pal++ = oldpal[off + 1];
                         *pal++ = oldpal[off + 2];
@@ -295,53 +297,61 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
 
     for (int i = smk->next_audio_index; i < 7; i++) {
         if (smk->flags & (1 << i)) {
-                uint32_t size;
+            uint32_t size;
 
-                size = avio_rl32(s->pb);
-            if ((int)size < 8 || size > smk->frame_size) {
-                    av_log(s, AV_LOG_ERROR, "Invalid audio part size\n");
-                    ret = AVERROR_INVALIDDATA;
-                    goto next_frame;
-                }
+            size = avio_rl32(s->pb);
+            if ((int)size < 4 + smk->duration_size[i] || size > smk->frame_size) {
+                av_log(s, AV_LOG_ERROR, "Invalid audio part size\n");
+                ret = AVERROR_INVALIDDATA;
+                goto next_frame;
+            }
             smk->frame_size -= size;
-                size       -= 4;
+            size            -= 4;
 
-            if (smk->indexes[i] < 0) {
-                avio_skip(s->pb, size);
+            if (smk->indexes[i] < 0 ||
+                s->streams[smk->indexes[i]]->discard >= AVDISCARD_ALL) {
+                smk->aud_pts[i] += smk->duration_size[i] ? avio_rl32(s->pb)
+                                                         : size;
+                avio_skip(s->pb, size - smk->duration_size[i]);
                 continue;
             }
             if ((ret = av_get_packet(s->pb, pkt, size)) != size) {
                 ret = ret < 0 ? ret : AVERROR_INVALIDDATA;
-                    goto next_frame;
-                }
+                goto next_frame;
+            }
             pkt->stream_index = smk->indexes[i];
             pkt->pts          = smk->aud_pts[i];
-            smk->aud_pts[i]  += AV_RL32(pkt->data);
+            pkt->duration     = smk->duration_size[i] ? AV_RL32(pkt->data)
+                                                      : size;
+            smk->aud_pts[i]  += pkt->duration;
             smk->next_audio_index = i + 1;
             return 0;
-            }
         }
+    }
 
+    if (s->streams[smk->videoindex]->discard >= AVDISCARD_ALL) {
+        ret = FFERROR_REDO;
+        goto next_frame;
+    }
     if (smk->frame_size >= INT_MAX/2) {
-            ret = AVERROR_INVALIDDATA;
-            goto next_frame;
-        }
+        ret = AVERROR_INVALIDDATA;
+        goto next_frame;
+    }
     if ((ret = av_new_packet(pkt, smk->frame_size + 769)) < 0)
-            goto next_frame;
+        goto next_frame;
     flags = smk->new_palette;
-        if(smk->frm_size[smk->cur_frame] & 1)
+    if (smk->frm_size[smk->cur_frame] & 1)
         flags |= 2;
     pkt->data[0] = flags;
-        memcpy(pkt->data + 1, smk->pal, 768);
+    memcpy(pkt->data + 1, smk->pal, 768);
     ret = ffio_read_size(s->pb, pkt->data + 769, smk->frame_size);
-        if (ret < 0)
-            goto next_frame;
-        pkt->stream_index = smk->videoindex;
-        pkt->pts          = smk->cur_frame;
-        pkt->size = ret + 769;
+    if (ret < 0)
+        goto next_frame;
+    pkt->stream_index = smk->videoindex;
+    pkt->pts          = smk->cur_frame;
     smk->next_audio_index = 0;
     smk->new_palette = 0;
-        smk->cur_frame++;
+    smk->cur_frame++;
 
     return 0;
 next_frame:
@@ -351,21 +361,37 @@ next_frame:
     return ret;
 }
 
-static int smacker_read_close(AVFormatContext *s)
+static int smacker_read_seek(AVFormatContext *s, int stream_index,
+                             int64_t timestamp, int flags)
 {
     SmackerContext *smk = s->priv_data;
+    int64_t ret;
+
+    /* only rewinding to start is supported */
+    if (timestamp != 0) {
+        av_log(s, AV_LOG_ERROR,
+               "Random seeks are not supported (can only seek to start).\n");
+        return AVERROR(EINVAL);
+    }
+
+    if ((ret = avio_seek(s->pb, s->internal->data_offset, SEEK_SET)) < 0)
+        return ret;
 
-    av_freep(&smk->frm_size);
+    smk->cur_frame = 0;
+    smk->next_audio_index = 0;
+    smk->new_palette = 0;
+    memset(smk->pal, 0, sizeof(smk->pal));
+    memset(smk->aud_pts, 0, sizeof(smk->aud_pts));
 
     return 0;
 }
 
-AVInputFormat ff_smacker_demuxer = {
+const AVInputFormat ff_smacker_demuxer = {
     .name           = "smk",
     .long_name      = NULL_IF_CONFIG_SMALL("Smacker"),
     .priv_data_size = sizeof(SmackerContext),
     .read_probe     = smacker_probe,
     .read_header    = smacker_read_header,
     .read_packet    = smacker_read_packet,
-    .read_close     = smacker_read_close,
+    .read_seek      = smacker_read_seek,
 };