2
* ZoneMinder MPEG class implementation, $Date: 2011-05-15 21:38:51 +0100 (Sun, 15 May 2011) $, $Revision: 3338 $
3
* Copyright (C) 2001-2008 Philip Coombes
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28
bool VideoStream::initialised = false;
30
VideoStream::MimeData VideoStream::mime_data[] = {
31
{ "asf", "video/x-ms-asf" },
32
{ "swf", "application/x-shockwave-flash" },
33
{ "flv", "video/x-flv" },
34
{ "mp4", "video/mp4" },
35
{ "move", "video/quicktime" }
38
void VideoStream::Initialise()
44
void VideoStream::SetupFormat( const char *p_filename, const char *p_format )
46
filename = p_filename;
49
/* auto detect the output format from the name. default is mpeg. */
50
of = av_guess_format( format, NULL, NULL);
53
Warning( "Could not deduce output format from file extension: using mpeg" );
54
of = av_guess_format("mpeg", NULL, NULL);
58
Fatal( "Could not find suitable output format" );
61
/* allocate the output media context */
62
ofc = (AVFormatContext *)av_mallocz(sizeof(AVFormatContext));
65
Panic( "Memory error" );
68
snprintf( ofc->filename, sizeof(ofc->filename), "%s", filename );
71
void VideoStream::SetupCodec( int colours, int width, int height, int bitrate, double frame_rate )
73
pf = (colours==1?PIX_FMT_GRAY8:PIX_FMT_RGB24);
75
/* add the video streams using the default format codecs
76
and initialize the codecs */
78
if (of->video_codec != CODEC_ID_NONE)
80
ost = av_new_stream(ofc, 0);
83
Panic( "Could not alloc stream" );
87
AVCodecContext *c = ost->codec;
89
AVCodecContext *c = &ost->codec;
92
c->codec_id = of->video_codec;
93
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
94
c->codec_type = AVMEDIA_TYPE_VIDEO;
96
c->codec_type = CODEC_TYPE_VIDEO;
99
/* put sample parameters */
100
c->bit_rate = bitrate;
101
c->pix_fmt = PIX_FMT_YUV420P;
102
/* resolution must be a multiple of two */
106
/* time base: this is the fundamental unit of time (in seconds) in terms
107
of which frame timestamps are represented. for fixed-fps content,
108
timebase should be 1/framerate and timestamp increments should be
110
//c->time_base.den = (int)(frame_rate*100);
111
//c->time_base.num = 100;
112
c->time_base.den = frame_rate;
113
c->time_base.num = 1;
115
/* frames per second */
116
c->frame_rate = frame_rate;
117
c->frame_rate_base = 1;
119
//c->gop_size = frame_rate/2; /* emit one intra frame every half second or so */
121
if ( c->gop_size < 3 )
123
// some formats want stream headers to be seperate
124
if(!strcmp(ofc->oformat->name, "mp4") || !strcmp(ofc->oformat->name, "mov") || !strcmp(ofc->oformat->name, "3gp"))
125
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
129
void VideoStream::SetParameters()
131
/* set the output parameters (must be done even if no
133
if ( av_set_parameters(ofc, NULL) < 0 )
135
Panic( "Invalid output format parameters" );
137
//dump_format(ofc, 0, filename, 1);
140
const char *VideoStream::MimeType() const
142
for ( int i = 0; i < sizeof(mime_data)/sizeof(*mime_data); i++ )
144
if ( strcmp( format, mime_data[i].format ) == 0 )
146
return( mime_data[i].mime_type );
149
const char *mime_type = of->mime_type;
152
mime_type = "video/mpeg";
153
Warning( "Unable to determine mime type for '%s' format, using '%s' as default", format, mime_type );
159
void VideoStream::OpenStream()
161
/* now that all the parameters are set, we can open the
162
video codecs and allocate the necessary encode buffers */
166
AVCodecContext *c = ost->codec;
168
AVCodecContext *c = &ost->codec;
171
/* find the video encoder */
172
AVCodec *codec = avcodec_find_encoder(c->codec_id);
175
Panic( "codec not found" );
179
if ( avcodec_open(c, codec) < 0 )
181
Panic( "Could not open codec" );
184
/* allocate the encoded raw picture */
185
opicture = avcodec_alloc_frame();
188
Panic( "Could not allocate opicture" );
190
int size = avpicture_get_size( c->pix_fmt, c->width, c->height);
191
uint8_t *opicture_buf = (uint8_t *)malloc(size);
195
Panic( "Could not allocate opicture" );
197
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height );
199
/* if the output format is not RGB24, then a temporary RGB24
200
picture is needed too. It is then converted to the required
203
if ( c->pix_fmt != pf )
205
tmp_opicture = avcodec_alloc_frame();
208
Panic( "Could not allocate temporary opicture" );
210
int size = avpicture_get_size( pf, c->width, c->height);
211
uint8_t *tmp_opicture_buf = (uint8_t *)malloc(size);
212
if (!tmp_opicture_buf)
214
av_free( tmp_opicture );
215
Panic( "Could not allocate temporary opicture" );
217
avpicture_fill( (AVPicture *)tmp_opicture, tmp_opicture_buf, pf, c->width, c->height );
221
/* open the output file, if needed */
222
if ( !(of->flags & AVFMT_NOFILE) )
224
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
225
if ( avio_open(&ofc->pb, filename, URL_WRONLY) < 0 )
227
if ( url_fopen(&ofc->pb, filename, URL_WRONLY) < 0 )
230
Fatal( "Could not open '%s'", filename );
235
if ( !(ofc->oformat->flags & AVFMT_RAWPICTURE) )
237
/* allocate output buffer */
238
/* XXX: API change will be done */
239
video_outbuf_size = 200000;
240
video_outbuf = (uint8_t *)malloc(video_outbuf_size);
243
/* write the stream header, if any */
244
av_write_header(ofc);
247
VideoStream::VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int width, int height )
254
SetupFormat( filename, format );
255
SetupCodec( colours, width, height, bitrate, frame_rate );
259
VideoStream::~VideoStream()
261
/* close each codec */
265
avcodec_close(ost->codec);
267
avcodec_close(&ost->codec);
269
av_free(opicture->data[0]);
273
av_free(tmp_opicture->data[0]);
274
av_free(tmp_opicture);
276
av_free(video_outbuf);
279
/* write the trailer, if any */
280
av_write_trailer(ofc);
282
/* free the streams */
283
for( int i = 0; i < ofc->nb_streams; i++)
285
av_freep(&ofc->streams[i]);
288
if (!(of->flags & AVFMT_NOFILE))
290
/* close the output file */
292
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
298
url_fclose(&ofc->pb);
302
/* free the stream */
306
double VideoStream::EncodeFrame( uint8_t *buffer, int buffer_size, bool add_timestamp, unsigned int timestamp )
308
#ifdef HAVE_LIBSWSCALE
309
static struct SwsContext *img_convert_ctx = 0;
310
#endif // HAVE_LIBSWSCALE
317
pts = (double)ost->pts.val * ofc->pts_num / ofc->pts_den;
319
pts = (double)ost->pts.val * ost->time_base.num / ost->time_base.den;
324
AVCodecContext *c = ost->codec;
326
AVCodecContext *c = &ost->codec;
328
if ( c->pix_fmt != pf )
330
memcpy( tmp_opicture->data[0], buffer, buffer_size );
331
#ifdef HAVE_LIBSWSCALE
332
if ( !img_convert_ctx )
334
img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
335
if ( !img_convert_ctx )
336
Panic( "Unable to initialise image scaling context" );
338
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize );
339
#else // HAVE_LIBSWSCALE
340
img_convert( (AVPicture *)opicture, c->pix_fmt, (AVPicture *)tmp_opicture, pf, c->width, c->height );
341
#endif // HAVE_LIBSWSCALE
345
memcpy( opicture->data[0], buffer, buffer_size );
347
AVFrame *opicture_ptr = opicture;
350
if ( ofc->oformat->flags & AVFMT_RAWPICTURE )
353
ret = av_write_frame( ofc, ost->index, (uint8_t *)opicture_ptr, sizeof(AVPicture) );
356
av_init_packet( &pkt );
358
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
359
pkt.flags |= AV_PKT_FLAG_KEY;
361
pkt.flags |= PKT_FLAG_KEY;
363
pkt.stream_index = ost->index;
364
pkt.data = (uint8_t *)opicture_ptr;
365
pkt.size = sizeof(AVPicture);
367
ret = av_write_frame(ofc, &pkt);
373
ost->pts.val = timestamp;
374
int out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, opicture_ptr);
378
ret = av_write_frame(ofc, ost->index, video_outbuf, out_size);
381
av_init_packet(&pkt);
384
pkt.pts = c->coded_frame->pts;
386
pkt.pts= av_rescale_q( c->coded_frame->pts, c->time_base, ost->time_base );
388
if(c->coded_frame->key_frame)
389
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1)
390
pkt.flags |= AV_PKT_FLAG_KEY;
392
pkt.flags |= PKT_FLAG_KEY;
394
pkt.stream_index = ost->index;
395
pkt.data = video_outbuf;
398
ret = av_write_frame( ofc, &pkt );
404
Fatal( "Error %d while writing video frame: %s", ret, strerror( errno ) );
409
#endif // HAVE_LIBAVCODEC