Почему новая версия ffmpeg так застревает в файлах http без чередования? - PullRequest
0 голосов
/ 14 июля 2020
  • Я использую AVAssetWriter / AVAssetWriterInput MA C для создания MP4, затем загружаю его на веб-сайт, а затем использую последнюю версию (ffmpeg4.2 или 4.3) ffplay для воспроизведения файла. как файл https на Windows, но я считаю, что он очень застрял. Использую старую версию ffmpeg Например версия 3.4 нормальная. Анализируя старый и новый исходный код ffmpeg, можно найти общую проблему, но более глубокая причина все еще неясна.

  • Аудио и видео кадры, записанные MA C, частично (в течение 3 секунд) без чередования

  • Последняя версия ffplay в Window продолжит переподключение http к Seek. В файле mov. c обнаружено, что номер AVIndexEntry созданный новой и старой версиями ffmpeg отличается, потому что размер буфера чтения определяется вычислением ff_configure_buffers_for_index: buffer_size новой версии AVIOContext только по умолчанию 16k, поэтому предварительный шаг mov_read_packet avio_seek обнаруживает, что pos следующего кадра выходит за пределы диапазона 16k, что приводит к повторному подключению к http и поиску новой позиции; в то время как AVIOContext.buffer_size старой версии ffmpeg имеет размер уровня M байтов, он не вызовет повторного подключения http.

  • Дальнейший анализ показал, что ff_configure_buffers_for_index будет рассчитываться на основе относительное максимальное смещение AVIndexEntry каждого потока, потому что новая версия пропускает возможность настроить buffer_size, потому что pos_delta больше 1 << 24. </p>

  • Но я не знаю почему в новой версии AVIndexEntry такая ситуация. Вы знаете, почему «новая» версия внесла это изменение? А как сделать так, чтобы плеер играл так же плавно, как старая версия?

     void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)
     {
         int ist1, ist2;
         int64_t pos_delta = 0;
         int64_t skip = 0;
         //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable
         const char *proto = avio_find_protocol_name(s->filename);
    
         if (!proto) {
             av_log(s, AV_LOG_INFO,
                "Protocol name not provided, cannot determine if input is local or "
                "a network protocol, buffers and access patterns cannot be configured "
                "optimally without knowing the protocol\n");
         }
    
         if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))
             return;
    
         for (ist1 = 0; ist1 < s->nb_streams; ist1++) {
             AVStream *st1 = s->streams[ist1];
             for (ist2 = 0; ist2 < s->nb_streams; ist2++) {
                 AVStream *st2 = s->streams[ist2];
                 int i1, i2;
    
                 if (ist1 == ist2)
                     continue;
    
                 for (i1 = i2 = 0; i1 < st1->nb_index_entries; i1++) {
                     AVIndexEntry *e1 = &st1->index_entries[i1];
                     int64_t e1_pts = av_rescale_q(e1->timestamp, st1->time_base, AV_TIME_BASE_Q);
    
                     skip = FFMAX(skip, e1->size);
                     for (; i2 < st2->nb_index_entries; i2++) {
                         AVIndexEntry *e2 = &st2->index_entries[i2];
                         int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q);
                         if (e2_pts - e1_pts < time_tolerance)
                             continue;
                         pos_delta = FFMAX(pos_delta, e1->pos - e2->pos);
                         av_log(s, AV_LOG_VERBOSE, "ff_configure_buffers_for_index  [%d, %d]  (%"PRId64", %"PRId64"):    %"PRId64"\n",  i1, i2, e1_pts, e2_pts, pos_delta);
                         break;
                     }
                 }
             }
         }
    
         pos_delta *= 2;
         /* XXX This could be adjusted depending on protocol*/
         if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) {
             av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);
             ffio_set_buf_size(s->pb, pos_delta);
             s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, pos_delta/2);
         }
    
         if (skip < (1<<23)) {
             s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, skip);
         }
     }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...