Code stream encapsulation using open Source Library FFmpeg
The H264 stream is written to H264 buffer via the function h264buff_write (), and mux_thread the received stream into the MP4 file.
Here I use a separate thread encapsulation stream is to solve the recording process of the cycle of the problem, or can not be separate pull thread.
Type declaration
/*---------------for muxing--------------*/
#ifndef int64_c
#define INT64_C (c) (C # # LL)
#define Uint64_c (c) (C # # ULL)
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#define Stream_frame_rate
#define STREAM_PIX_FMT pix_fmt_yuv420p/ * av_pix_fmt_yuv420p */* Default PIX_FMT */
static int
h264buff_write (char *buf, int n, int instns);
global variable Declaration
static int h264buff_flag = 0;
sem_t Sem_f;
static Char h264bufa[5242880];/*5mb*///[54857600]; /*50mb*/
static char h264bufb[5242880];//[54857600];
static int a_size;
static int b_size;
function declaration
/*------------------------muxing---------------------------------*/*-----------------< 0 = Error 0 = i-frame 1 = P-frame 2 = b-frame 3 = s-frame--------------------*/static 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;
} B + = 3;
/* Verify VOP ID */if (0xb6 = = *b) {b++;
Return (*b & 0xc0) >> 6;
} switch (*b) {case 0x65:return 0;
Case 0x61:return 1;
Case 0x01:return 2;
} return-1;
} static 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;
} B + = 3;
Return (*b & 0x1f); }/* Add an OUTPUT stream */static Avstream *add_stream (AVFormatcontext *oc, Avcodec **codec, struct mux_priv *mux_p, void *p, int len) {Avcodeccontext *PCC;
Avstream *pst;
Avbitstreamfiltercontext * Avfilter;
Enum Codecid codec_id = codec_id_h264;
PST = Av_new_stream (OC, 0);
if (!pst) {printf ("could not allocate stream \ n");
return NULL;
} Pst->id = oc->nb_streams-1;
PCC = pst->codec;
Mux_p->vi = pst->index;
Avcodec_get_context_defaults2 (PCC, NULL);
pcc->codec_id = codec_id;
Pcc->codec_type = Codec_type_video;
Pcc->bit_rate = 3000000;
Pcc->width = 720;
Pcc->height = 480;
Pcc->time_base.den = 30;
Pcc->time_base.num = 1;
Pcc->frame_number = 1;
Pcc->gop_size = 12;
PCC->PIX_FMT = stream_pix_fmt;
Avfilter = Av_bitstream_filter_init ("H264_mp4toannexb");
Pcc->extradata_size = Len; Pcc->extradata = (uint8_t*) p;
/*set the PPS SPS of H264 */printf ("\n\nzorro, pcc->codec_id =%d. \ n", (int) pcc->codec_id); if (Oc->oformat->flags & Avfmt_globAlheader) {pcc->flags |= codec_flag_global_header;
} return PST; } static int CreateMp4 (Avformatcontext **pm_poc, char *pszfilename, struct mux_priv *mux_p, void *p, int len) {int R Et
Successfully returned 0, failed to return 1//const char* pszfilename = "Output002.mp4";
Avoutputformat *fmt;
Avcodec *video_codec;
Avstream *m_pvideost;
Avformatcontext *m_poc;
/*0x67 or 0x27*/if (0x07! = Get_nal_type (P, Len)) {printf ("Can not detect nal type");
return-1;
} av_register_all (); /* Auto detect the output format from the name. Default is MPEG.
*/FMT = Guess_format (null, pszfilename, NULL);
if (!fmt) {printf ("Could not deduce output format from file extension:using mpeg.\n");
FMT = Guess_format ("MPEG", pszFileName, NULL);
} if (!fmt) {fprintf (stderr, "Could not find suitable output format\n");
return-1;//}/* Allocate the output media context */M_poc = Av_alloc_format_context ();
*pm_poc = M_poc;
if (!M_POC) {fprintf (stderr, "Memory error\n");
return-1;
} M_poc->oformat = FMT;
snprintf (m_poc->filename, sizeof (M_poc->filename), "%s", pszFileName);
if (fmt->video_codec! = Codec_id_none) {if (M_pvideost = Add_stream (M_poc, &video_codec, Mux_p, p, len) = = NULL) {
return-1; }}/* Set the output parameters (must is done even if no parameters).
*/if (Av_set_parameters (M_poc, NULL) < 0) {printf ("Invalid output format parameters\n");
return-1;
} dump_format (M_poc, 0, pszFileName, 1); /* Open the output file, if needed */if (!) Fmt->flags & Avfmt_nofile) {if (Url_fopen (&M_POC->PB, pszFileName, url_wronly) < 0) {printf ("Coul
D not open '%s ' \ n ', pszfilename);
return-1;
}}/* Write The stream header, if any */ret = Av_write_header (M_POC);
if (Ret < 0) {printf ("Error occurred when opening output file");
return-1;
} return 0; }/* Write H264 data to MP4 file */static int writevideo (Avformatcontext *m_poc, struct mux_priv *mux_p, void* data, int Nlen) {int ret;
if (0 > Mux_p->vi) {printf ("Vi less than 0");
return-1;
} Avstream *pst = m_poc->streams[mux_p->vi];
Init packet Avpacket PKT;
My add, in order to calculate pts avcodeccontext *c = pst->codec;
Av_init_packet (&PKT); Pkt.flags |= (0 >= getvoptype (data, Nlen))?
pkt_flag_key:0;
Pkt.stream_index = pst->index;
Pkt.data = (uint8_t*) data;
Pkt.size = Nlen;
Wait for key frame if (Mux_p->waitkey) if (0 = = (Pkt.flags & pkt_flag_key)) return 0;
else Mux_p->waitkey = 0;
Pkt.dts = Av_nopts_value;
pkt.pts = Av_nopts_value;
Pkt.pts = (ptsinc++) * (180000/stream_frame_rate);
Pkt.dts = (ptsinc++) * (90000/stream_frame_rate);
ret = Av_interleaved_write_frame (M_poc, &PKT);
if (Ret < 0) {printf ("Cannot write frame");
} av_free_packet (&PKT);
return 0;
} static void CloseMp4 (Avformatcontext *m_poc) {/* no need Zorro Waitkey =-1; VI =-1;
*/if (M_POC) Av_write_trailer (M_POC); If (M_poc &&!)
(M_poc->oformat->flags & Avfmt_nofile)) Url_fclose (M_POC->PB);/* for New:avio_close (M_POC->PB);
*/if (M_POC) {av_free (M_POC);
M_poc = NULL; }}/*==============get_h264nal================ *function:get a NAL from H264buff,when we find the next NAL, ret Urn 0, or return-1, *author:zorro *date:6/3/2015 *======================================*/static int get_h264nal (void
*pbuff, int plen, int *nal_len, int *nal_type) {unsigned char *h264data = (unsigned char*) pbuff;
int h264len = Plen;
int next_type;
if (Plen <4) {*nal_len = Plen;
return-1; }//Check this NAL type if (h264data[1] | | H264DATA[2] | |
0x01! = H264data[3]) {*nal_type = 0;
}else{*nal_type = h264data[4] & 0x1f;
h264data+=4;
h264len-=4; } while (H264len) {if (h264data[0] = = 0x00 && h264data[1] = = 0x00 && h264data[2] = = 0x01) {Next_typ
E = h264data[3] & 0x1f; if (Next_type = = 0x01 | | Next_type = = 0x05) {if (h264data[-1] = = 0x00) h264data--;
*nal_len = H264data-(unsigned char *) pbuff;
return 0;
}} h264data+=1;
H264len-=1;
} *nal_len = H264data-(unsigned char *) pbuff;
return-1; }/*==============mux_thread==================== *function:read h264data from H264 file, and packet it to MP4 file *aut Hor:zorro *date:6/3/2015 *======================================*/void mux_thread (void *arg) {struct Encode *enc = (
struct encode *) arg;
int instns = enc->cmdl->instns;
struct Mux_priv mux_p = {0,-1, 1};
Char *h264head;
int H264len;
unsigned char nalbuf[512 * 1024];
int Nal_len;
int Read_len;
int nal_type;
int RS;
Avformatcontext * Pformatctx = NULL;
Waitenc:sem_wait (& Sem_f);
if (H264buff_flag = = 1) {h264head = H264bufa;
H264len = a_size;
a_size = 0;
}else{h264head = H264BUFB;
H264len = b_size;
b_size = 0; } do{/* reach the next NAL or h264buf end*/rs = get_h264nal (H264head, H264leN, &read_len, &nal_type);
if ((H264len-read_len) < 0) {printf ("\n\n\nzorro, get_h264nal err.\n\n");
}/* No data to read, break out*/if (read_len <= 0) break;
/* New nal*/if (Nal_type > 0) {memcpy (Nalbuf, H264head, Read_len);
Nal_len = Read_len; if (Nal_type = = 0x05) Mux_p.waitkey = 1;
/*check key frame*/}else{/* Last nal*/memcpy (&nalbuf[nal_len], h264head, Read_len);
Nal_len + = Read_len;
} H264head + = Read_len;
H264len-= Read_len;
/* Reach the h264buf end */if (Rs < 0) {if (! enc_end) goto Waitenc;
printf ("reach the H264 buff end, H264len =%d, Nal_len =%d, Nal_type =%d\n", H264len, Nal_len, Nal_type);
} if (0 < Nal_len) {memset (&nalbuf[nal_len], 0, ff_input_buffer_padding_size); if (!pformatctx) {if (CREATEMP4 (&pformatctx, Enc->cmdl->output, &mux_p, Nalbuf, Nal_len) < 0) {bre
Ak }} if (Pformatctx) if (Writevideo (Pformatctx, &Amp;mux_p, Nalbuf, Nal_len) < 0) break;
}/* End if (0 < Nal_len) */if (quitflag) break;
}while (0 < Nal_len);
CLOSEMP4 (PFORMATCTX); Ins_priv[instns].
a_size = 0; Ins_priv[instns].
b_size = 0;
printf ("\nmuxing end\n"); }/*==============h264buff_write================ *function:copy The encoded data Frome Vpu to H264buff, *author:zorro * date:6/3/2015 *======================================*/static int h264buff_write (char *buf, int n, int instns) {//if (
Fwrite_thread_err < 0)//return-1; if (! H264buff_flag) {if (a_size >= 5000000) {printf ("Zorro,memory err, out of H264bufa range:
\ n ");
return-1;
} memcpy (void *) (& h264bufa[A_size]), (void *) BUF, n);
A_size+=n;
if (a_size >= 5000000) {h264buff_flag = 1;
Sem_post (& Sem_f); }}else{if (b_size >= 5000000) {printf ("Zorro,memory err, out of H264BUFB range:
\ n ");
return-1;
} memcpy (void *) (& h264bufb[B_size]), (void *) BUF, n); B_siZe+=n;
if (b_size >= 5000000) {h264buff_flag = 0;
Sem_post (& Sem_f);
}} return 0; }/*------------------------muxing---------------------------------*/