update format and aspect ratio choices by Andrew
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / ffmpeg.C
index b3915cfc44de133644e71180239b519170199d2d..97b6698acbb2ffc342f93049dbd54537d0a39235 100644 (file)
@@ -270,7 +270,8 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx)
        frm_count = 0;
        nudge = AV_NOPTS_VALUE;
        seek_pos = curr_pos = 0;
-       seeked = 1;  eof = 0;
+       seeking = 0; seeked = 1;
+       eof = 0;
        reading = writing = 0;
        hw_pixfmt = AV_PIX_FMT_NONE;
        hw_device_ctx = 0;
@@ -714,6 +715,7 @@ int FFStream::seek(int64_t no, double rate)
                }
        }
        if( pos == curr_pos ) return 0;
+       seeking = -1;
        double secs = pos < 0 ? 0. : pos / rate;
        AVRational time_base = st->time_base;
        int64_t tstmp = time_base.num > 0 ? secs * time_base.den/time_base.num : 0;
@@ -1220,10 +1222,36 @@ int FFVideoStream::load(VFrame *vframe, int64_t pos)
                return -1;
        }
        int i = MAX_RETRY + pos - curr_pos;
+       int64_t cache_start = 0;
        while( ret>=0 && !flushed && curr_pos<=pos && --i>=0 ) {
                ret = read_frame(frame);
-               if( ret > 0 ) ++curr_pos;
+               if( ret > 0 ) {
+                       if( frame->key_frame && seeking < 0 ) {
+                               int use_cache = ffmpeg->get_use_cache();
+                               if( use_cache < 0 ) {
+// for reverse read, reload file frame_cache from keyframe to pos
+                                       ffmpeg->purge_cache();
+                                       int count = preferences->cache_size /
+                                               vframe->get_data_size() / 2;  // try to burn only 1/2 of cache
+                                       cache_start = pos - count + 1;
+                                       seeking = 1;
+                               }
+                               else
+                                       seeking = 0;
+                       }
+                       if( seeking > 0 && curr_pos >= cache_start && curr_pos < pos ) {
+                               int vw =vframe->get_w(), vh = vframe->get_h();
+                               int vcolor_model = vframe->get_color_model();
+// do not use shm here, puts too much pressure on 32bit systems
+                               VFrame *cache_frame = new VFrame(vw, vh, vcolor_model, 0);
+                               ret = convert_cmodel(cache_frame, frame);
+                               if( ret > 0 )
+                                       ffmpeg->put_cache_frame(cache_frame, curr_pos);
+                       }
+                       ++curr_pos;
+               }
        }
+       seeking = 0;
        if( frame->format == AV_PIX_FMT_NONE || frame->width <= 0 || frame->height <= 0 )
                ret = -1;
        if( ret >= 0 ) {
@@ -2217,6 +2245,21 @@ int FFMPEG::scan_options(const char *options, AVDictionary *&opts, AVStream *st)
        return ret;
 }
 
+void FFMPEG::put_cache_frame(VFrame *frame, int64_t position)
+{
+       file_base->file->put_cache_frame(frame, position, 0);
+}
+
+int FFMPEG::get_use_cache()
+{
+       return file_base->file->get_use_cache();
+}
+
+void FFMPEG::purge_cache()
+{
+       file_base->file->purge_cache();
+}
+
 FFCodecRemap::FFCodecRemap()
 {
        old_codec = 0;
@@ -3961,6 +4004,9 @@ double FFMPEG::get_initial_timecode(int data_type, int channel, double frame_rat
                fidx = aud->fidx;
                nudge = aud->nudge;
                st = aud->st;
+               AVDictionaryEntry *tref = av_dict_get(fmt_ctx->metadata, "time_reference", 0, 0);
+               if( tref && aud && aud->sample_rate )
+                       return strtod(tref->value, 0) / aud->sample_rate;
                break; }
        case TRACK_VIDEO: {
                codec_type = AVMEDIA_TYPE_VIDEO;