c - Raw H264 frames in mpegts container using libavcodec -


i appreciate following issue:

i have gadget camera, producing h264 compressed video frames, these frames being sent application. these frames not in container, raw data.

i want use ffmpeg , libav functions create video file, can used later.

if decode frames, encode them, works fine, valid video file. (the decode/encode steps usual libav commands, nothing fancy here, took them almighty internet, rock solid)... however, waste lot of time decoding , encoding, skip step , directly put frames in output stream. now, problems come.

here code came producing encoding:

avframe* picture;  avpicture_fill((avpicture*) picture, (uint8_t*)framedata,                   codeccontext->pix_fmt, codeccontext->width,                  codeccontext->height); int outsize = avcodec_encode_video(codeccontext, videooutbuf,                   sizeof(videooutbuf), picture); if (outsize > 0)  {     avpacket packet;     av_init_packet(&packet);     packet.pts = av_rescale_q(codeccontext->coded_frame->pts,                   codeccontext->time_base, videostream->time_base);     if (codeccontext->coded_frame->key_frame)      {         packet.flags |= pkt_flag_key;     }     packet.stream_index = videostream->index;     packet.data =  videooutbuf;     packet.size =  outsize;      av_interleaved_write_frame(context, &packet);     put_flush_packet(context->pb); } 

where variables like:

framedata decoded frame data, came camera, decoded in previous step , videooutbuf plain uint8_t buffer holding data

i have modified application in order not decode frames, pass through data like:

    avpacket packet;     av_init_packet(&packet);      packet.stream_index = videostream->index;     packet.data = (uint8_t*)framedata;     packet.size = currentframesize;      av_interleaved_write_frame(context, &packet);     put_flush_packet(context->pb); 

where

framedata raw h264 frame , currentframesize size of raw h264 frame, ie. number of bytes gadget every frame.

and application not working correctly anymore, produced video unplayable. obvious, since not setting correct pts packet. did following (i'm desperate, can see approach :) )

    packet.pts = timestamps[timestamp_counter ++]; 

where timestamps list of pts's produced working code above, , written file (yes, read properly, logged pts's 10 minute session, , wanted use them).

the application still not work.

now, here without clue do, here question:

i create "mpegts" video stream using libav functions, insert in stream encoded video frames , create video file it. how do it?

thanks, f.

i believe if set following, see video playback.

packet.flags |= av_pkt_flag_key; packet.pts = packet.dts = 0; 

you should set packet.flags according h264 packet headers. might try this fellow stack overflowian's suggestion extracting directly stream.

if adding audio, pts/dts going more important. suggest study this tutorial

edit

i found time extract out working me test app. reason, dts/pts values of 0 works me, values other 0 or av_nopts_value not. wonder if have different versions of ffmpeg. have latest git://git.videolan.org/ffmpeg.git.

fftest.cpp

#include <string>  #ifndef int64_c #define int64_c(c) (c ## ll) #define uint64_c(c) (c ## ull) #endif  //#define _m #define _m printf( "%s(%d) : marker\n", __file__, __line__ )  extern "c" {     #include "libavcodec/avcodec.h"     #include "libavformat/avformat.h" };   avformatcontext *fc = 0; int vi = -1, waitkey = 1;  // < 0 = error // 0 = i-frame // 1 = p-frame // 2 = b-frame // 3 = s-frame int getvoptype( const void *p, int len ) {        if ( !p || 6 >= len )         return -1;      unsigned char *b = (unsigned char*)p;      // verify nal marker     if ( b[ 0 ] || b[ 1 ] || 0x01 != b[ 2 ] )     {   b++;         if ( b[ 0 ] || b[ 1 ] || 0x01 != b[ 2 ] )             return -1;     } // end if      b += 3;      // verify vop id     if ( 0xb6 == *b )     {   b++;         return ( *b & 0xc0 ) >> 6;     } // end if      switch( *b )     {   case 0x65 : return 0;         case 0x61 : return 1;         case 0x01 : return 2;     } // end switch      return -1; }  void write_frame( const void* p, int len ) {     if ( 0 > vi )         return;      avstream *pst = fc->streams[ vi ];      // init packet     avpacket pkt;     av_init_packet( &pkt );     pkt.flags |= ( 0 >= getvoptype( p, len ) ) ? av_pkt_flag_key : 0;        pkt.stream_index = pst->index;     pkt.data = (uint8_t*)p;     pkt.size = len;      // wait key frame     if ( waitkey )         if ( 0 == ( pkt.flags & av_pkt_flag_key ) )             return;         else             waitkey = 0;      pkt.dts = av_nopts_value;     pkt.pts = av_nopts_value;  //  av_write_frame( fc, &pkt );     av_interleaved_write_frame( fc, &pkt ); }  void destroy() {     waitkey = 1;     vi = -1;      if ( !fc )         return;  _m; av_write_trailer( fc );      if ( fc->oformat && !( fc->oformat->flags & avfmt_nofile ) && fc->pb )         avio_close( fc->pb );       // free stream _m; av_free( fc );      fc = 0; _m;  }  int get_nal_type( void *p, int len ) {     if ( !p || 5 >= len )         return -1;      unsigned char *b = (unsigned char*)p;      // verify nal marker     if ( b[ 0 ] || b[ 1 ] || 0x01 != b[ 2 ] )     {   b++;         if ( b[ 0 ] || b[ 1 ] || 0x01 != b[ 2 ] )             return -1;     } // end if      b += 3;      return *b; }  int create( void *p, int len ) {     if ( 0x67 != get_nal_type( p, len ) )         return -1;      destroy();      const char *file = "test.avi";     codecid codec_id = codec_id_h264; //  codecid codec_id = codec_id_mpeg4;     int br = 1000000;     int w = 480;     int h = 354;     int fps = 15;      // create container _m; avoutputformat *of = av_guess_format( 0, file, 0 );     fc = avformat_alloc_context();     fc->oformat = of;     strcpy( fc->filename, file );      // add video stream _m; avstream *pst = av_new_stream( fc, 0 );     vi = pst->index;      avcodeccontext *pcc = pst->codec; _m; avcodec_get_context_defaults2( pcc, avmedia_type_video );     pcc->codec_type = avmedia_type_video;      pcc->codec_id = codec_id;     pcc->bit_rate = br;     pcc->width = w;     pcc->height = h;     pcc->time_base.num = 1;     pcc->time_base.den = fps;      // init container _m; av_set_parameters( fc, 0 );      if ( !( fc->oformat->flags & avfmt_nofile ) )         avio_open( &fc->pb, fc->filename, url_wronly );  _m; av_write_header( fc );  _m; return 1; }  int main( int argc, char** argv ) {     int f = 0, sz = 0;     char fname[ 256 ] = { 0 };     char buf[ 128 * 1024 ];      av_log_set_level( av_log_error );     av_register_all();          {         // raw frames in v0.raw, v1.raw, v2.raw, ... //      sprintf( fname, "rawvideo/v%lu.raw", f++ );         sprintf( fname, "frames/frame%lu.bin", f++ );         printf( "%s\n", fname );          file *fd = fopen( fname, "rb" );         if ( !fd )             sz = 0;         else         {             sz = fread( buf, 1, sizeof( buf ) - ff_input_buffer_padding_size, fd );             if ( 0 < sz )             {                 memset( &buf[ sz ], 0, ff_input_buffer_padding_size );                            if ( !fc )                     create( buf, sz );                  if ( fc )                     write_frame( buf, sz );              } // end if              fclose( fd );          } // end else      } while ( 0 < sz );      destroy(); } 

Comments

Popular posts from this blog

c# - how to write client side events functions for the combobox items -

exception - Python, pyPdf OCR error: pyPdf.utils.PdfReadError: EOF marker not found -