]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/dv.c
avutil: Add missing test programs to Makefile.
[ffmpeg] / libavformat / dv.c
index 78e3b38d18c36ade35198e2e3262762c34b38727..f38b9546053e862012a8429870d097fea5973e18 100644 (file)
  * Copyright (c) 2006 Daniel Maas <dmaas@maasdigital.com>
  * Funded by BBC Research & Development
  *
- * This file is part of FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include <time.h>
 #include "avformat.h"
 #include "libavcodec/dvdata.h"
 #include "libavutil/intreadwrite.h"
+#include "libavutil/mathematics.h"
 #include "dv.h"
 
 struct DVDemuxContext {
@@ -214,14 +215,14 @@ static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame)
            if (!c->ast[i])
                break;
            av_set_pts_info(c->ast[i], 64, 1, 30000);
-           c->ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;
+           c->ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO;
            c->ast[i]->codec->codec_id   = CODEC_ID_PCM_S16LE;
 
            av_init_packet(&c->audio_pkt[i]);
            c->audio_pkt[i].size         = 0;
            c->audio_pkt[i].data         = c->audio_buf[i];
            c->audio_pkt[i].stream_index = c->ast[i]->index;
-           c->audio_pkt[i].flags       |= PKT_FLAG_KEY;
+           c->audio_pkt[i].flags       |= AV_PKT_FLAG_KEY;
        }
        c->ast[i]->codec->sample_rate = dv_audio_frequency[freq];
        c->ast[i]->codec->channels    = 2;
@@ -290,7 +291,7 @@ DVDemuxContext* dv_init_demux(AVFormatContext *s)
     c->frames = 0;
     c->abytes = 0;
 
-    c->vst->codec->codec_type = CODEC_TYPE_VIDEO;
+    c->vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
     c->vst->codec->codec_id   = CODEC_ID_DVVIDEO;
     c->vst->codec->bit_rate   = 25000000;
     c->vst->start_time        = 0;
@@ -322,7 +323,7 @@ int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
     uint8_t *ppcm[4] = {0};
 
     if (buf_size < DV_PROFILE_BYTES ||
-        !(c->sys = dv_frame_profile(c->sys, buf, buf_size)) ||
+        !(c->sys = ff_dv_frame_profile(c->sys, buf, buf_size)) ||
         buf_size < c->sys->frame_size) {
           return -1;   /* Broken frame, or not enough data */
     }
@@ -336,15 +337,18 @@ int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
        ppcm[i] = c->audio_buf[i];
     }
     dv_extract_audio(buf, ppcm, c->sys);
-    c->abytes += size;
 
     /* We work with 720p frames split in half, thus even frames have
      * channels 0,1 and odd 2,3. */
     if (c->sys->height == 720) {
-        if (buf[1] & 0x0C)
+        if (buf[1] & 0x0C) {
             c->audio_pkt[2].size = c->audio_pkt[3].size = 0;
-        else
+        } else {
             c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
+            c->abytes += size;
+        }
+    } else {
+        c->abytes += size;
     }
 
     /* Now it's time to return video packet */
@@ -352,7 +356,7 @@ int dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
     av_init_packet(pkt);
     pkt->data         = buf;
     pkt->size         = size;
-    pkt->flags       |= PKT_FLAG_KEY;
+    pkt->flags       |= AV_PKT_FLAG_KEY;
     pkt->stream_index = c->vst->id;
     pkt->pts          = c->frames;
 
@@ -365,17 +369,17 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
                               int64_t timestamp, int flags)
 {
     // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
-    const DVprofile* sys = dv_codec_profile(c->vst->codec);
+    const DVprofile* sys = ff_dv_codec_profile(c->vst->codec);
     int64_t offset;
-    int64_t size = url_fsize(s->pb);
+    int64_t size = avio_size(s->pb) - s->data_offset;
     int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size;
 
     offset = sys->frame_size * timestamp;
 
-    if (offset > max_offset) offset = max_offset;
+    if (size >= 0 && offset > max_offset) offset = max_offset;
     else if (offset < 0) offset = 0;
 
-    return offset;
+    return offset + s->data_offset;
 }
 
 void dv_offset_reset(DVDemuxContext *c, int64_t frame_offset)
@@ -407,28 +411,28 @@ static int dv_read_header(AVFormatContext *s,
     if (!c->dv_demux)
         return -1;
 
-    state = get_be32(s->pb);
+    state = avio_rb32(s->pb);
     while ((state & 0xffffff7f) != 0x1f07003f) {
-        if (url_feof(s->pb)) {
+        if (s->pb->eof_reached) {
             av_log(s, AV_LOG_ERROR, "Cannot find DV header.\n");
             return -1;
         }
         if (state == 0x003f0700 || state == 0xff3f0700)
-            marker_pos = url_ftell(s->pb);
-        if (state == 0xff3f0701 && url_ftell(s->pb) - marker_pos == 80) {
-            url_fseek(s->pb, -163, SEEK_CUR);
-            state = get_be32(s->pb);
+            marker_pos = avio_tell(s->pb);
+        if (state == 0xff3f0701 && avio_tell(s->pb) - marker_pos == 80) {
+            avio_seek(s->pb, -163, SEEK_CUR);
+            state = avio_rb32(s->pb);
             break;
         }
-        state = (state << 8) | get_byte(s->pb);
+        state = (state << 8) | avio_r8(s->pb);
     }
     AV_WB32(c->buf, state);
 
-    if (get_buffer(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) <= 0 ||
-        url_fseek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
+    if (avio_read(s->pb, c->buf + 4, DV_PROFILE_BYTES - 4) <= 0 ||
+        avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0)
         return AVERROR(EIO);
 
-    c->dv_demux->sys = dv_frame_profile(c->dv_demux->sys, c->buf, DV_PROFILE_BYTES);
+    c->dv_demux->sys = ff_dv_frame_profile(c->dv_demux->sys, c->buf, DV_PROFILE_BYTES);
     if (!c->dv_demux->sys) {
         av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n");
         return -1;
@@ -452,7 +456,7 @@ static int dv_read_packet(AVFormatContext *s, AVPacket *pkt)
         if (!c->dv_demux->sys)
             return AVERROR(EIO);
         size = c->dv_demux->sys->frame_size;
-        if (get_buffer(s->pb, c->buf, size) <= 0)
+        if (avio_read(s->pb, c->buf, size) <= 0)
             return AVERROR(EIO);
 
         size = dv_produce_packet(c->dv_demux, pkt, c->buf, size);
@@ -470,7 +474,7 @@ static int dv_read_seek(AVFormatContext *s, int stream_index,
 
     dv_offset_reset(c, offset / c->sys->frame_size);
 
-    offset = url_fseek(s->pb, offset, SEEK_SET);
+    offset = avio_seek(s->pb, offset, SEEK_SET);
     return (offset < 0) ? offset : 0;
 }
 
@@ -485,6 +489,8 @@ static int dv_probe(AVProbeData *p)
 {
     unsigned state, marker_pos = 0;
     int i;
+    int matches = 0;
+    int secondary_matches = 0;
 
     if (p->buf_size < 5)
         return 0;
@@ -492,19 +498,28 @@ static int dv_probe(AVProbeData *p)
     state = AV_RB32(p->buf);
     for (i = 4; i < p->buf_size; i++) {
         if ((state & 0xffffff7f) == 0x1f07003f)
-            return AVPROBE_SCORE_MAX*3/4; // not max to avoid dv in mov to match
+            matches++;
+        // any section header, also with seq/chan num != 0,
+        // should appear around every 12000 bytes, at least 10 per frame
+        if ((state & 0xff07ff7f) == 0x1f07003f)
+            secondary_matches++;
         if (state == 0x003f0700 || state == 0xff3f0700)
             marker_pos = i;
         if (state == 0xff3f0701 && i - marker_pos == 80)
-            return AVPROBE_SCORE_MAX/4;
+            matches++;
         state = (state << 8) | p->buf[i];
     }
 
+    if (matches && p->buf_size / matches < 1024*1024) {
+        if (matches > 4 || (secondary_matches >= 10 && p->buf_size / secondary_matches < 24000))
+            return AVPROBE_SCORE_MAX*3/4; // not max to avoid dv in mov to match
+        return AVPROBE_SCORE_MAX/4;
+    }
     return 0;
 }
 
 #if CONFIG_DV_DEMUXER
-AVInputFormat dv_demuxer = {
+AVInputFormat ff_dv_demuxer = {
     "dv",
     NULL_IF_CONFIG_SMALL("DV video format"),
     sizeof(RawDVContext),