
Recherche avancée
Médias (1)
-
La conservation du net art au musée. Les stratégies à l’œuvre
26 mai 2011
Mis à jour : Juillet 2013
Langue : français
Type : Texte
Autres articles (79)
-
Le profil des utilisateurs
12 avril 2011, parChaque utilisateur dispose d’une page de profil lui permettant de modifier ses informations personnelle. Dans le menu de haut de page par défaut, un élément de menu est automatiquement créé à l’initialisation de MediaSPIP, visible uniquement si le visiteur est identifié sur le site.
L’utilisateur a accès à la modification de profil depuis sa page auteur, un lien dans la navigation "Modifier votre profil" est (...) -
Configurer la prise en compte des langues
15 novembre 2010, parAccéder à la configuration et ajouter des langues prises en compte
Afin de configurer la prise en compte de nouvelles langues, il est nécessaire de se rendre dans la partie "Administrer" du site.
De là, dans le menu de navigation, vous pouvez accéder à une partie "Gestion des langues" permettant d’activer la prise en compte de nouvelles langues.
Chaque nouvelle langue ajoutée reste désactivable tant qu’aucun objet n’est créé dans cette langue. Dans ce cas, elle devient grisée dans la configuration et (...) -
Sélection de projets utilisant MediaSPIP
29 avril 2011, parLes exemples cités ci-dessous sont des éléments représentatifs d’usages spécifiques de MediaSPIP pour certains projets.
Vous pensez avoir un site "remarquable" réalisé avec MediaSPIP ? Faites le nous savoir ici.
Ferme MediaSPIP @ Infini
L’Association Infini développe des activités d’accueil, de point d’accès internet, de formation, de conduite de projets innovants dans le domaine des Technologies de l’Information et de la Communication, et l’hébergement de sites. Elle joue en la matière un rôle unique (...)
Sur d’autres sites (9471)
-
How to accurately/precisely seek to a timestamp in media with ffmpeg API ?
11 novembre 2024, par wangt13I am writing a simple audio player with
ffmpeg
ver.4.4.4, and I want to seek to specific timestamp of the audio media (a MP3 file).

Here is my code.
I am using
avformat_seek_file()
with flags ofAVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD
, and when I setseek_pos
to 10 second when it is playing frames of 3rd second, it seemed NOT jump to the 10th second, it only played the audios after 3rd second !

Then I added the code skipping/discarding the packets whose pts is before the seek position. This time, it loops in the
if (curr_s < seek_ts)
, not going to 10th seconds.

It seemed NO
keyframe
at 10th second.

void decode_func(...)
{
 while (1) {
 if (av_read_frame(pfmtctx, packet) < 0) {
 avcodec_flush_buffers(pcodectx);
 printf("Got end of media, breaking\n");
 break;
 }
 /**
 * Discard the packet of pts before seek position
 */
 curr_s = packet->pts * av_q2d(pfmtctx->streams[stream]->time_base);
 if (seek_ts) {
 if (curr_s < seek_ts) {
 avcodec_flush_buffers(pcodectx);
 av_frame_unref(pFrame);
 continue;
 } else {
 seek_ts = 0;
 }
 }
 if (seek_req) {
 int64_t seek_abs;
 seek_req = 0;
 seek_abs = (seek_pos)*AV_TIME_BASE;
 printf("Seek to %lld, pts: %lld\n", seek_abs, packet->pts;
 if (seek_abs < 0) {
 seek_abs = 0;
 }
 if (avformat_seek_file(pfmtctx, -1, INT64_MIN, seek_abs, INT64_MAX, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD) >= 0) {
 avcodec_flush_buffers(pcodectx);
 seek_ts = seek_abs;
 continue;
 } else {
 printf("Failed to seek to %lld\n", seek_abs);
 seek_ts = 0;
 }
 }

 res = avcodec_send_packet(pcodectx, packet);
 while (res >= 0) {
 res = avcodec_receive_frame(pcodectx, pFrame);
 if (res == AVERROR(EAGAIN)) {
 break;
 } else if (res == AVERROR_EOF) {
 break;
 } else if (res >= 0) {
 /// Processing decoded frame
 }
 av_frame_unref(frame);
 }
}



So, how can I precisely (almost) seek to a timestamp with FFMPEG ?


-
avformat/mm : fix packets pts generation and add seek support
26 juin 2024, par Paul B Mahol -
How to seek one frame forward in ffmpeg [closed]
10 mars, par Summiti want to seek one frame forward when i call this function but it gets stuck on the first frame seeked and does not move forward.


void seekFrameUp() {
 if (!fmt_ctx || video_stream_index == -1) return;

 AVRational frame_rate = fmt_ctx->streams[video_stream_index]->r_frame_rate;
 if (frame_rate.num == 0) return; // Avoid division by zero

 // Compute frame duration in AV_TIME_BASE_Q
 int64_t frame_duration = av_rescale_q(1,
 av_make_q(frame_rate.den, frame_rate.num),
 AV_TIME_BASE_Q);

 int64_t next_pts = requestedTimestamp + frame_duration;

 qDebug() << "Seeking forward: " << next_pts
 << " (Current PTS: " << requestedTimestamp
 << ", Frame Duration: " << frame_duration << ")";

 requestFrameAt(next_pts);

 // Update the requested timestamp after seeking
 requestedTimestamp = next_pts;
}





void requestFrameAt(int64_t timestamp) {
 {
 std::lock_guard lock(mtx);
 decoding = true; // Ensure the thread keeps decoding when needed
 }
 cv.notify_one();
 }


void decodeLoop() {
 while (!stopThread) {
 std::unique_lock lock(mtx);
 cv.wait(lock, [this] { return decoding || stopThread; });

 if (stopThread) break;

 // Avoid redundant seeking
 if (requestedTimestamp == lastRequestedTimestamp) {
 decoding = false;
 continue;
 }

 

 lastRequestedTimestamp.store(requestedTimestamp.load());
 int64_t target_pts = av_rescale_q(requestedTimestamp, AV_TIME_BASE_Q, fmt_ctx->streams[video_stream_index]->time_base);

 target_pts = FFMAX(target_pts, 0); // Ensure it's not negative

 if (av_seek_frame(fmt_ctx, video_stream_index, target_pts, AVSEEK_FLAG_ANY) >= 0) {
 avcodec_flush_buffers(codec_ctx); // Clear old frames from the decoder
 qDebug() << "Seek successful to PTS:" << target_pts;
 }
 else {
 qDebug() << "Seeking failed!";
 decoding = false;
 continue;
 }

 lock.unlock();

 // Keep decoding until we receive a valid frame
 bool frameDecoded = false;
 while (av_read_frame(fmt_ctx, pkt) >= 0) {
 if (pkt->stream_index == video_stream_index) {
 if (avcodec_send_packet(codec_ctx, pkt) == 0) {
 while (avcodec_receive_frame(codec_ctx, frame) == 0) {
 qDebug() << "FRAME DECODED ++++++++++++ PTS:" << frame->pts;
 if (frame->pts != AV_NOPTS_VALUE) {
 // Rescale PTS to AV_TIME_BASE_Q
 int64_t pts_in_correct_base = av_rescale_q(frame->pts,
 fmt_ctx->streams[video_stream_index]->time_base,
 AV_TIME_BASE_Q);

 // Ensure we don’t reset to 0 incorrectly
 if (pts_in_correct_base > 0) {
 current_pts.store(pts_in_correct_base);
 qDebug() << "Updated current_pts to:" << current_pts.load();
 }
 else {
 qDebug() << "Warning: Decoded frame has PTS <= 0, keeping last valid PTS.";
 }
 }
 else {
 qDebug() << "Invalid frame->pts (AV_NOPTS_VALUE)";
 }

 QImage img = convertFrameToImage(frame);
 emit frameDecodedSignal(img);
 
 frameDecoded = true;
 break; // Exit after the first valid frame
 }

 if (frameDecoded) {
 decoding = (requestedTimestamp != lastRequestedTimestamp);
 break;
 }
 }
 }
 av_packet_unref(pkt);
 }
 }
}