2013-07-09 2 views
12

Я пишу видеоредактор, и мне нужно искать точную рамку, зная номер кадра .Как я могу найти номер кадра X с ffmpeg?

Другие сообщения в stackoverflow сказали мне, что ffmpeg может дать мне несколько сломанных кадров после поиска, что не является проблемой для воспроизведения, но большая проблема для видеоредакторов.

И мне нужно искать на номера кадра, не по времени, которое станет неточным при преобразовании в кадр номер.

Я прочитал Tuts dranger (которые являются устаревшим в настоящее время), и в конечном итоге с:

av_seek_frame(fmt_ctx, video_stream_id, frame, AVSEEK_FLAG_ANY); 

Он всегда стремится к кадру No. 0, и всегда return 0 что означает успех. Затем я попытался прочитать исходный код Блендера и нашел его очень сложным (может быть, я должен реализовать буфер изображений?).

Итак, есть ли простой способ поиска кадра с помощью простого вызова типа seek(context, frame_number) (при получении полного кадра, а не сломанного)? Или, есть ли облегченная библиотека, которая упрощает это?

EDIT: Благодаря praks411, я нашел решение:

void AV_seek(AV * av, size_t frame) 
{ 
    int frame_delta = frame - av->frame_id; 
    if (frame_delta < 0 || frame_delta > 5) 
     av_seek_frame(av->fmt_ctx, av->video_stream_id, 
       frame, AVSEEK_FLAG_BACKWARD); 
    while (av->frame_id != frame) 
     AV_read_frame(av); 
} 

void AV_read_frame(AV * av) 
{ 
    AVPacket packet; 
    int frame_done; 

    while (av_read_frame(av->fmt_ctx, &packet) >= 0) { 
     if (packet.stream_index == av->video_stream_id) { 
      avcodec_decode_video2(av->codec_ctx, av->frame, &frame_done, &packet); 
      if (frame_done) { 
       ... 
       av->frame_id = packet.dts; 
       av_free_packet(&packet); 
       return; 
      } 
     } 
     av_free_packet(&packet); 
    } 
} 
+0

вы гарантировано фиксированный стабильный фпс? Затем вы можете искать по времени. См. Также обсуждение «key-frame» – rogerdpack

+0

только пользователь знает. это может быть видео с переменной частотой кадров. – Giumo

ответ

6

av_seek_frame будет получать только основываясь на метку времени в замочную кадра. Поскольку он ищет ключевой кадр, вы можете не получить то, что хотите. Поэтому рекомендуется искать ближайший ключевой кадр, а затем читать кадр за кадром, если вы достигнете нужного кадра.

Однако, если вы имеете дело с фиксированным значением FPS, вы можете легко сопоставить временную метку с индексом кадра.

Перед тем, как искать, вам нужно будет преобразовать ваше время в AVStream.time_base единиц, если вы указали поток. Прочтите документацию ffmpeg от av_seek_frame в avformat.h.

Например, если вы хотите обратиться к 1.23 секунд клипа:

double m_out_start_time = 1.23; 
int flgs = AVSEEK_FLAG_ANY; 
int seek_ts = (m_out_start_time*(m_in_vid_strm->time_base.den))/(m_in_vid_strm->time_base.num); 
if(av_seek_frame(m_informat, m_in_vid_strm_idx,seek_ts, flgs) < 0) 
{ 
    PRINT_MSG("Failed to seek Video ") 
} 
+1

О, и я, наконец, знаю, что документация находится в файлах заголовков, неудивительно, что я не могу найти ни одного онлайн. – Giumo

+0

Затем, как я могу узнать, где находится ближайший ключевой кадр? – Giumo

+0

Это не time_base.den/time_base.num fps? Не seek_ts = time * fps номер кадра? – Giumo

Смежные вопросы