3 Copyright (C) 2005 Cockos Incorporated
4 Copyright (C) 1999-2004 Nullsoft, Inc.
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
28 #include "../sdks/ffmpeg/include/stdint.h"
29 #include "../sdks/ffmpeg/include/inttypes.h"
34 #include "../sdks/ffmpeg/include/libavformat/avformat.h"
35 #include "../sdks/ffmpeg/include/libswscale/swscale.h"
41 #define INT64_C(val) val##i64
46 #define INT64_MIN (-0x7fffffffffffffff##i64 - 1)
48 #define INT64_MIN (-0x7fffffffffffffffLL - 1)
53 #define INT64_MAX INT64_C(9223372036854775807)
59 //bitrates are in kbps
60 WDL_VideoEncode(const char *format
, int width
, int height
, double fps
, int bitrate
, const char *audioformat
=NULL
, int asr
=44100, int ach
=2, int abitrate
=0)
63 m_img_resample_ctx
= NULL
;
69 avcodec_get_frame_defaults(&m_cvtpic
);
74 if(!init
) av_register_all();
78 m_ctx
= av_alloc_format_context();
79 AVOutputFormat
*fmt
= guess_format(format
, NULL
, NULL
);
80 if(!m_ctx
|| !fmt
) return;
84 m_stream
= av_new_stream(m_ctx
, m_ctx
->nb_streams
);
88 avcodec_get_context_defaults2(m_stream
->codec
, CODEC_TYPE_VIDEO
);
89 m_video_enc
= m_stream
->codec
;
91 CodecID codec_id
= av_guess_codec(m_ctx
->oformat
, NULL
, NULL
, NULL
, CODEC_TYPE_VIDEO
);
92 m_video_enc
->codec_id
= codec_id
;
95 codec
= avcodec_find_encoder(codec_id
);
98 m_video_enc
->width
= width
;
99 m_video_enc
->height
= height
;
100 m_video_enc
->time_base
.den
= fps
* 10000;
101 m_video_enc
->time_base
.num
= 10000;
103 m_video_enc
->pix_fmt
= PIX_FMT_BGRA
;
104 if (codec
&& codec
->pix_fmts
)
106 const enum PixelFormat
*p
= codec
->pix_fmts
;
107 for (; *p
!=-1; p
++) {
108 if (*p
== m_video_enc
->pix_fmt
)
112 m_video_enc
->pix_fmt
= codec
->pix_fmts
[0];
115 if(m_video_enc
->pix_fmt
!= PIX_FMT_BGRA
)
117 //this codec needs colorplane conversion
118 int sws_flags
= SWS_BICUBIC
;
119 m_img_resample_ctx
= sws_getContext(
125 m_video_enc
->pix_fmt
,
126 sws_flags
, NULL
, NULL
, NULL
);
128 if ( avpicture_alloc( (AVPicture
*)&m_cvtpic
, m_video_enc
->pix_fmt
,
129 m_video_enc
->width
, m_video_enc
->height
) )
133 m_video_enc
->bit_rate
= bitrate
*1024;
134 m_video_enc
->gop_size
= 12; /* emit one intra frame every twelve frames at most */
136 // some formats want stream headers to be separate
137 if(m_ctx
->oformat
->flags
& AVFMT_GLOBALHEADER
)
138 m_video_enc
->flags
|= CODEC_FLAG_GLOBAL_HEADER
;
140 m_video_enc
->max_qdiff
= 3; // set the default maximum quantizer difference between frames
141 m_video_enc
->thread_count
= 1; // set how many thread need be used in encoding
142 m_video_enc
->rc_override_count
= 0; // set ratecontrol override to 0
143 if (!m_video_enc
->rc_initial_buffer_occupancy
)
145 m_video_enc
->rc_initial_buffer_occupancy
= m_video_enc
->rc_buffer_size
*3/4; // set decoder buffer size
147 m_video_enc
->me_threshold
= 0; // set motion estimation threshold value to 0
148 m_video_enc
->intra_dc_precision
= 0;
149 m_video_enc
->strict_std_compliance
= 0;
150 m_ctx
->preload
= (int)(0.5 * AV_TIME_BASE
);
151 m_ctx
->max_delay
= (int)(0.7 * AV_TIME_BASE
);
152 m_ctx
->loop_output
= -1;
154 m_ctx
->timestamp
= 0;
156 av_log_set_callback(ffmpeg_avcodec_log
);
157 av_log_set_level(AV_LOG_ERROR
);
159 if (avcodec_open(m_video_enc
, codec
) < 0)
167 m_astream
= av_new_stream(m_ctx
, m_ctx
->nb_streams
);
168 if(!m_astream
) return;
170 avcodec_get_context_defaults2(m_astream
->codec
, CODEC_TYPE_AUDIO
);
171 m_audio_enc
= m_astream
->codec
;
173 //use the format's default audio codec
174 CodecID codeca_id
= av_guess_codec(m_ctx
->oformat
, audioformat
, NULL
, NULL
, CODEC_TYPE_AUDIO
);
175 m_audio_enc
->codec_id
= codeca_id
;
178 acodec
= avcodec_find_encoder(codeca_id
);
181 m_audio_enc
->bit_rate
= abitrate
*1024;
182 m_audio_enc
->sample_rate
= asr
;
183 m_audio_enc
->channels
= ach
;
185 if (avcodec_open(m_audio_enc
, acodec
) < 0) return;
188 AVFormatParameters params
, *ap
= ¶ms
;
189 memset(ap
, 0, sizeof(*ap
));
190 if (av_set_parameters(m_ctx
, ap
) < 0) return;
192 url_open_dyn_buf(&m_ctx
->pb
);
193 av_write_header(m_ctx
);
195 int size
= width
* height
;
196 m_bit_buffer_size
= 1024 * 256;
197 m_bit_buffer_size
= FFMAX(m_bit_buffer_size
, 4*size
);
199 m_bit_buffer
= (uint8_t*)av_malloc(m_bit_buffer_size
);
205 if(m_stream
&& m_stream
->codec
) avcodec_close(m_stream
->codec
);
206 if(m_astream
&& m_astream
->codec
) avcodec_close(m_astream
->codec
);
207 av_free(m_bit_buffer
);
208 av_free(m_cvtpic
.data
[0]);
212 int isInited() { return m_init
; }
214 void encodeVideo(const LICE_pixel
*buf
)
216 if(m_img_resample_ctx
)
218 //convert to output format
219 uint8_t *p
[1]={(uint8_t*)buf
};
220 int w
[1]={m_video_enc
->width
*4};
221 sws_scale(m_img_resample_ctx
, p
, w
,
222 0, m_video_enc
->height
, m_cvtpic
.data
, m_cvtpic
.linesize
);
224 int ret
= avcodec_encode_video(m_video_enc
, m_bit_buffer
, m_bit_buffer_size
, &m_cvtpic
);
228 av_init_packet(&pkt
);
229 pkt
.stream_index
= 0;
230 pkt
.data
= m_bit_buffer
;
232 if (m_video_enc
->coded_frame
->pts
!= AV_NOPTS_VALUE
)
233 pkt
.pts
= av_rescale_q(m_video_enc
->coded_frame
->pts
, m_video_enc
->time_base
, m_stream
->time_base
);
234 if(m_video_enc
->coded_frame
->key_frame
)
235 pkt
.flags
|= PKT_FLAG_KEY
;
236 av_interleaved_write_frame(m_ctx
, &pkt
);
240 void encodeAudio(short *data
, int nbsamples
)
244 int fs
= m_audio_enc
->frame_size
*m_audio_enc
->channels
;
247 av_init_packet(&pkt
);
248 pkt
.size
= avcodec_encode_audio(m_audio_enc
, m_bit_buffer
, m_bit_buffer_size
, data
);
249 if (m_audio_enc
->coded_frame
->pts
!= AV_NOPTS_VALUE
)
250 pkt
.pts
= av_rescale_q(m_audio_enc
->coded_frame
->pts
, m_audio_enc
->time_base
, m_astream
->time_base
);
251 pkt
.flags
|= PKT_FLAG_KEY
;
252 pkt
.stream_index
= 1;
253 pkt
.data
= m_bit_buffer
;
254 av_interleaved_write_frame(m_ctx
, &pkt
);
261 int getBytes(unsigned char *p
, int size
)
263 //looks like there's no other way to get data from ffmpeg's dynamic buffers apart from closing them
264 if (m_queue
.GetSize() < size
&& m_init
)
267 int l
= url_close_dyn_buf(m_ctx
-> pb
, &pb_buffer
);
270 m_queue
.Add(pb_buffer
, l
);
273 url_open_dyn_buf(&m_ctx
->pb
); //sets up next dynamic buffer for ffmpeg
276 int s
= wdl_min(size
, m_queue
.GetSize());
279 memcpy(p
, m_queue
.Get(), s
);
288 av_write_trailer(m_ctx
);
290 int l
= url_close_dyn_buf(m_ctx
-> pb
, &pb_buffer
);
293 m_queue
.Add(pb_buffer
, l
);
299 //useful to get debugging information from ffmpeg
300 static void ffmpeg_avcodec_log(void *ptr
, int val
, const char * msg
, va_list ap
)
302 AVClass
* avc
= ptr
? *(AVClass
**)ptr
: NULL
;
309 AVFormatContext
*m_ctx
;
310 AVStream
*m_stream
, *m_astream
;
311 AVCodecContext
*m_video_enc
, *m_audio_enc
;
312 struct SwsContext
*m_img_resample_ctx
;
314 uint8_t *m_bit_buffer
;
315 int m_bit_buffer_size
;
320 class WDL_VideoDecode
323 WDL_VideoDecode(const char *fn
)
337 if(!init
) av_register_all();
341 int ret
= av_open_input_file(&m_ic
, fn
, NULL
, 0, NULL
);
344 ret
= av_find_stream_info(m_ic
);
347 // find the stream that corresponds to the stream type
349 for(i
=0; i
< (int)m_ic
->nb_streams
; i
++)
351 int st
= m_ic
->streams
[i
]->codec
->codec_type
;
352 if(st
==CODEC_TYPE_VIDEO
)
358 if(stream
==-1) return; //no stream found
360 m_ctx
= m_ic
->streams
[stream
]->codec
;
362 AVCodec
*pCodec
= avcodec_find_decoder(m_ctx
->codec_id
);
363 if(pCodec
== NULL
) return; // codec not found
365 if(avcodec_open(m_ctx
, pCodec
)<0) return; // Could not open codec
367 AVStream
*st
= m_ic
->streams
[stream
];
368 if(st
->r_frame_rate
.den
&& st
->r_frame_rate
.num
)
369 m_fps
= av_q2d(st
->r_frame_rate
);
371 m_fps
= 1/av_q2d(st
->codec
->time_base
);
373 m_frame
= avcodec_alloc_frame();
378 m_pixfmt
=st
->codec
->pix_fmt
;
380 if(m_ic
->duration
== AV_NOPTS_VALUE
)
382 //FFmpeg can't get the duration
383 //approximate the duration of the file with the first packets bitrates
384 AVStream
*st
= m_ic
->streams
[stream
];
386 for(i
=0; i
< (int)m_ic
->nb_streams
; i
++)
388 bitrate
+= m_ic
->streams
[i
]->codec
->bit_rate
;
392 m_len
= (double)m_ic
->file_size
/bitrate
;
394 m_len
= 30; //last resort
397 m_len
= (double)m_ic
->duration
/AV_TIME_BASE
;
404 if(m_frame
) av_free(m_frame
);
405 if(m_ic
) av_close_input_file(m_ic
);
406 if(m_sws
) sws_freeContext(m_sws
);
408 int isInited() { return m_inited
; }
409 int GetVideoFrameAtTime(LICE_IBitmap
*dst
, double atTime
, double *startTime
, double *endTime
, bool resizeToBuf
)
411 if(!m_inited
) return 0;
412 if(m_curtime
== -1.0 || atTime
<m_curtime
|| (atTime
-m_curtime
)>(1.0/m_fps
))
414 if(avformat_seek_file(m_ic
, -1, INT64_MIN
, atTime
*AV_TIME_BASE
, INT64_MAX
, AVSEEK_FLAG_BACKWARD
) < 0)
416 //fallback to old seeking API
417 av_seek_frame(m_ic
, -1, atTime
*AV_TIME_BASE
, AVSEEK_FLAG_BACKWARD
);
419 avcodec_flush_buffers(m_ctx
);
422 double startpts
= -1;
426 if(av_read_frame(m_ic
, &packet
)<0) return 0; //end of file
427 if(packet
.stream_index
==m_stream
)
429 double packetpts
= getPresentationTime(&packet
);
430 if(startpts
== -1) startpts
= packetpts
;
432 int frameFinished
= 0;
433 int l
= avcodec_decode_video(m_ctx
, m_frame
, &frameFinished
, packet
.data
, packet
.size
);
436 // Did we get a video frame?
439 double pts
= startpts
;
440 double epts
= packetpts
+(1.0/m_fps
);
444 //keep decoding until we get to the desired seek frame
445 startpts
= packetpts
;
449 if(startTime
) *startTime
= pts
;
450 if(endTime
) *endTime
= epts
;
453 //convert decoded image to correct format
459 h
= dst
->getHeight();
465 unsigned int *bits
= dst
->getBits();
467 uint8_t *dstd[4]= {(uint8_t *)bits+(dst->getRowSpan()*4*(h-1)),};
468 int dst_stride[4]={-dst->getRowSpan()*4,};
470 uint8_t *dstd
[4]= {(uint8_t *)bits
,};
471 int dst_stride
[4]={dst
->getRowSpan()*4,};
474 if (!m_sws
|| m_sws_desth
!= h
|| m_sws_destw
!= w
)
476 int sws_flags
= SWS_BICUBIC
;
483 if(m_sws
) sws_freeContext(m_sws
);
484 m_sws
= sws_getContext(m_w
, m_h
, m_pixfmt
, w
, h
, pfout
, sws_flags
, NULL
, NULL
, NULL
);
490 sws_scale(m_sws
, m_frame
->data
, m_frame
->linesize
, 0, m_h
, dstd
, dst_stride
);
492 av_free_packet(&packet
);
497 av_free_packet(&packet
);
506 double getPresentationTime(AVPacket
*packet
)
509 if(packet
->dts
!= AV_NOPTS_VALUE
) mpts
= (double)packet
->dts
;
510 mpts
*= av_q2d(m_ic
->streams
[packet
->stream_index
]->time_base
);
511 mpts
-= (double)m_ic
->start_time
/AV_TIME_BASE
;
517 AVFormatContext
*m_ic
;
518 AVCodecContext
*m_ctx
;
524 int m_w
, m_h
, m_format
;
526 struct SwsContext
*m_sws
;
527 int m_sws_desth
, m_sws_destw
;
528 PixelFormat m_pixfmt
;