Merge remote-tracking branch 'qatar/master'
[ffmpeg.git] / libavformat / ffmdec.c
index 1145767..86e31cc 100644 (file)
@@ -1,21 +1,21 @@
 /*
- * FFM (avserver live feed) demuxer
+ * FFM (ffserver live feed) demuxer
  * Copyright (c) 2001 Fabrice Bellard
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg 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.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -24,7 +24,7 @@
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
-#if CONFIG_AVSERVER
+#if CONFIG_FFSERVER
 #include <unistd.h>
 
 int64_t ffm_read_write_index(int fd)
@@ -56,7 +56,7 @@ void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size)
     ffm->write_index = pos;
     ffm->file_size = file_size;
 }
-#endif // CONFIG_AVSERVER
+#endif // CONFIG_FFSERVER
 
 static int ffm_is_avail_data(AVFormatContext *s, int size)
 {
@@ -93,7 +93,7 @@ static int ffm_resync(AVFormatContext *s, int state)
 {
     av_log(s, AV_LOG_ERROR, "resyncing\n");
     while (state != PACKET_ID) {
-        if (s->pb->eof_reached) {
+        if (url_feof(s->pb)) {
             av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n");
             return -1;
         }
@@ -122,6 +122,11 @@ static int ffm_read_data(AVFormatContext *s,
             if (avio_tell(pb) == ffm->file_size)
                 avio_seek(pb, ffm->packet_size, SEEK_SET);
     retry_read:
+            if (pb->buffer_size != ffm->packet_size) {
+                int64_t tell = avio_tell(pb);
+                url_setbufsize(pb, ffm->packet_size);
+                avio_seek(pb, tell, SEEK_SET);
+            }
             id = avio_rb16(pb); /* PACKET_ID */
             if (id != PACKET_ID)
                 if (ffm_resync(s, id) < 0)
@@ -167,7 +172,7 @@ static int ffm_read_data(AVFormatContext *s,
 
 /* ensure that acutal seeking happens between FFM_PACKET_SIZE
    and file_size - FFM_PACKET_SIZE */
-static void ffm_seek1(AVFormatContext *s, int64_t pos1)
+static int64_t ffm_seek1(AVFormatContext *s, int64_t pos1)
 {
     FFMContext *ffm = s->priv_data;
     AVIOContext *pb = s->pb;
@@ -176,7 +181,7 @@ static void ffm_seek1(AVFormatContext *s, int64_t pos1)
     pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE);
     pos = FFMAX(pos, FFM_PACKET_SIZE);
     av_dlog(s, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos);
-    avio_seek(pb, pos, SEEK_SET);
+    return avio_seek(pb, pos, SEEK_SET);
 }
 
 static int64_t get_dts(AVFormatContext *s, int64_t pos)
@@ -320,8 +325,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
             codec->qcompress = avio_rb16(pb) / 10000.0;
             codec->qblur = avio_rb16(pb) / 10000.0;
             codec->bit_rate_tolerance = avio_rb32(pb);
-            avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
-            codec->rc_eq = av_strdup(rc_eq_buf);
+            codec->rc_eq = av_strdup(get_strz(pb, rc_eq_buf, sizeof(rc_eq_buf)));
             codec->rc_max_rate = avio_rb32(pb);
             codec->rc_min_rate = avio_rb32(pb);
             codec->rc_buffer_size = avio_rb32(pb);
@@ -345,6 +349,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
             codec->thread_count = avio_r8(pb);
             codec->coder_type = avio_rb32(pb);
             codec->me_cmp = avio_rb32(pb);
+            codec->partitions = avio_rb32(pb);
             codec->me_subpel_quality = avio_rb32(pb);
             codec->me_range = avio_rb32(pb);
             codec->keyint_min = avio_rb32(pb);
@@ -354,6 +359,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
             codec->qblur = av_int2dbl(avio_rb64(pb));
             codec->max_qdiff = avio_rb32(pb);
             codec->refs = avio_rb32(pb);
+            codec->directpred = avio_rb32(pb);
             break;
         case AVMEDIA_TYPE_AUDIO:
             codec->sample_rate = avio_rb32(pb);
@@ -461,11 +467,25 @@ static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, in
     av_dlog(s, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
     /* find the position using linear interpolation (better than
        dichotomy in typical cases) */
-    pos_min = FFM_PACKET_SIZE;
-    pos_max = ffm->file_size - FFM_PACKET_SIZE;
+    if (ffm->write_index && ffm->write_index < ffm->file_size) {
+        if (get_dts(s, FFM_PACKET_SIZE) < wanted_pts) {
+            pos_min = FFM_PACKET_SIZE;
+            pos_max = ffm->write_index - FFM_PACKET_SIZE;
+        } else {
+            pos_min = ffm->write_index;
+            pos_max = ffm->file_size - FFM_PACKET_SIZE;
+        }
+    } else {
+        pos_min = FFM_PACKET_SIZE;
+        pos_max = ffm->file_size - FFM_PACKET_SIZE;
+    }
     while (pos_min <= pos_max) {
         pts_min = get_dts(s, pos_min);
         pts_max = get_dts(s, pos_max);
+        if (pts_min > wanted_pts || pts_max < wanted_pts) {
+            pos = pts_min > wanted_pts ? pos_min : pos_max;
+            goto found;
+        }
         /* linear interpolation */
         pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
             (double)(pts_max - pts_min);
@@ -487,7 +507,8 @@ static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, in
     pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max;
 
  found:
-    ffm_seek1(s, pos);
+    if (ffm_seek1(s, pos) < 0)
+        return -1;
 
     /* reset read state */
     ffm->read_state = READ_HEADER;
@@ -509,7 +530,7 @@ static int ffm_probe(AVProbeData *p)
 
 AVInputFormat ff_ffm_demuxer = {
     .name           = "ffm",
-    .long_name      = NULL_IF_CONFIG_SMALL("FFM (AVserver live feed) format"),
+    .long_name      = NULL_IF_CONFIG_SMALL("FFM (FFserver live feed) format"),
     .priv_data_size = sizeof(FFMContext),
     .read_probe     = ffm_probe,
     .read_header    = ffm_read_header,