[Libav-user] how to create seekable mkv using libavformat?

Jan Pohanka xhpohanka at gmail.com
Fri Sep 21 10:24:41 CEST 2012


Hello,

I'm muxing a raw h264 stream from hadrdware encoder to mkv using  
libavformat library. The resulting file is playable, but not properly  
seekable I'm testing it in ffplay - moving to certains times causes the  
image to disappear or break and there are these warnings:
[h264 @ 0x7f3298008500] Missing reference picture
[h264 @ 0x7f3298008500] decode_slice_header error

I think that the problem does not lie in the encoded stream, because when  
I try a following sequence on the file
ffmpeg -i vtest.mkv -vcodec copy -f rawvideo vtest.h264
ffmpeg -i vtest.h264 -vcodec copy vtest2.mkv
the resulting vtest2.mkv is then seekable without any problems

Below there is simplified code that I use to save the frames. Can please  
someone give me some advice how to alter it to make the resulting file  
seekable?

void *write_thread_f(void *arg)
{
     AVFormatContext *os;
     AVOutputFormat *fmt;
     AVStream *video_st;
...
     os = avformat_alloc_context();
     if (os == NULL)
         return NULL;

     fmt = av_guess_format(NULL, env->filename, NULL);
     if (!fmt) {
         fprintf(stderr, "Nemam vystupni format\n");
         goto write_cleanup;
     }

     os->oformat = fmt;
     strncpy(os->filename, env->filename, 128);

     video_st = av_new_stream(os, 0);
     if (!video_st) {
         goto write_cleanup;
     }

     video_st->codec->codec_id = CODEC_ID_H264;
     video_st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
     video_st->codec->time_base.num = curr_fmt->time_base.num;
     video_st->codec->time_base.den = curr_fmt->time_base.den;
     video_st->codec->width = env->width;
     video_st->codec->height = env->height;
     video_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

     if (avio_open(&os->pb, os->filename, URL_WRONLY) < 0) {
         goto write_cleanup;
     }

     avformat_write_header(os, NULL);

     t = 0;
     while (...) {
         struct buf_info *enc_buf;
         AVPacket pkt;

         ret = fifo_get(env->write_in_fifo, &enc_buf);
         if (ret == FIFO_FLUSH)
             goto write_cleanup2;

         av_init_packet(&pkt);
         pkt.data = enc_buf->user_addr;
         pkt.size = enc_buf->bytes_used;
         pkt.stream_index = video_st->index;
         pkt.pts = av_rescale_q(t++, video_st->codec->time_base,  
video_st->time_base);

         if (enc_buf->flags & BUF_IFRAME)
             pkt.flags |= AV_PKT_FLAG_KEY;

         av_interleaved_write_frame(os, &pkt);

         fifo_put(env->write_out_fifo, enc_buf);

     }

     env->recording = 0; /* end of recording */
     pthread_mutex_unlock(&env->rec_lock);

write_cleanup2:
     av_write_trailer(os);
     avio_close(os->pb);
write_cleanup:
     avformat_free_context(os);


regards
Jan

-- 
Tato zpráva byla vytvořena převratným poštovním klientem Opery:  
http://www.opera.com/mail/


More information about the Libav-user mailing list