19 #include <stdlib.h> |
19 #include <stdlib.h> |
20 #include <stdio.h> |
20 #include <stdio.h> |
21 #include <stdint.h> |
21 #include <stdint.h> |
22 #include <string.h> |
22 #include <string.h> |
23 #include <stdarg.h> |
23 #include <stdarg.h> |
|
24 |
|
25 #include "libavcodec/avcodec.h" |
24 #include "libavformat/avformat.h" |
26 #include "libavformat/avformat.h" |
|
27 #include "libavutil/avutil.h" |
25 #include "libavutil/mathematics.h" |
28 #include "libavutil/mathematics.h" |
26 |
|
27 #ifndef AVIO_FLAG_WRITE |
|
28 #define AVIO_FLAG_WRITE AVIO_WRONLY |
|
29 #endif |
|
30 |
29 |
31 #if (defined _MSC_VER) |
30 #if (defined _MSC_VER) |
32 #define AVWRAP_DECL __declspec(dllexport) |
31 #define AVWRAP_DECL __declspec(dllexport) |
33 #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun)) |
32 #elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun)) |
34 #define AVWRAP_DECL __attribute__((visibility("default"))) |
33 #define AVWRAP_DECL __attribute__((visibility("default"))) |
55 static FILE* g_pSoundFile; |
54 static FILE* g_pSoundFile; |
56 static int16_t* g_pSamples; |
55 static int16_t* g_pSamples; |
57 static int g_NumSamples; |
56 static int g_NumSamples; |
58 |
57 |
59 |
58 |
|
59 // compatibility section |
60 #if LIBAVCODEC_VERSION_MAJOR < 54 |
60 #if LIBAVCODEC_VERSION_MAJOR < 54 |
61 #define OUTBUFFER_SIZE 200000 |
61 #define OUTBUFFER_SIZE 200000 |
62 static uint8_t g_OutBuffer[OUTBUFFER_SIZE]; |
62 static uint8_t g_OutBuffer[OUTBUFFER_SIZE]; |
63 #endif |
63 #define avcodec_open2(x, y, z) avcodec_open(x, y) |
|
64 #endif |
|
65 |
|
66 #if LIBAVCODEC_VERSION_MAJOR < 56 |
|
67 #define av_frame_alloc avcodec_alloc_frame |
|
68 #define av_frame_free av_freep |
|
69 #define av_packet_rescale_ts rescale_ts |
|
70 |
|
71 static void rescale_ts(AVPacket *pkt, AVRational ctb, AVRational stb) |
|
72 { |
|
73 if (pkt->pts != AV_NOPTS_VALUE) |
|
74 pkt->pts = av_rescale_q(pkt->pts, ctb, stb); |
|
75 if (pkt->dts != AV_NOPTS_VALUE) |
|
76 pkt->dts = av_rescale_q(pkt->dts, ctb, stb); |
|
77 if (pkt->duration > 0) |
|
78 pkt->duration = av_rescale_q(pkt->duration, ctb, stb); |
|
79 } |
|
80 #endif |
|
81 |
|
82 #ifndef AV_CODEC_CAP_DELAY |
|
83 #define AV_CODEC_CAP_DELAY CODEC_CAP_DELAY |
|
84 #endif |
|
85 #ifndef AV_CODEC_CAP_VARIABLE_FRAME_SIZE |
|
86 #define AV_CODEC_CAP_VARIABLE_FRAME_SIZE CODEC_CAP_VARIABLE_FRAME_SIZE |
|
87 #endif |
|
88 #ifndef AV_CODEC_FLAG_GLOBAL_HEADER |
|
89 #define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER |
|
90 #endif |
|
91 #ifndef AV_CODEC_FLAG_QSCALE |
|
92 #define AV_CODEC_FLAG_QSCALE CODEC_FLAG_QSCALE |
|
93 #endif |
|
94 |
|
95 #if LIBAVFORMAT_VERSION_MAJOR < 53 |
|
96 #define AVIO_FLAG_WRITE AVIO_WRONLY |
|
97 #endif |
|
98 |
|
99 #if LIBAVFORMAT_VERSION_MAJOR < 54 |
|
100 #define avformat_new_stream(x, y) av_new_stream(x, y->type == AVMEDIA_TYPE_AUDIO) |
|
101 #endif |
|
102 |
|
103 #if LIBAVUTIL_VERSION_MAJOR < 54 |
|
104 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P |
|
105 #endif |
|
106 |
64 |
107 |
65 // pointer to function from hwengine (uUtils.pas) |
108 // pointer to function from hwengine (uUtils.pas) |
66 static void (*AddFileLogRaw)(const char* pString); |
109 static void (*AddFileLogRaw)(const char* pString); |
67 |
110 |
68 static int FatalError(const char* pFmt, ...) |
111 static int FatalError(const char* pFmt, ...) |
103 AddFileLogRaw(Buffer); |
146 AddFileLogRaw(Buffer); |
104 } |
147 } |
105 |
148 |
106 static void AddAudioStream() |
149 static void AddAudioStream() |
107 { |
150 { |
108 #if LIBAVFORMAT_VERSION_MAJOR >= 53 |
|
109 g_pAStream = avformat_new_stream(g_pContainer, g_pACodec); |
151 g_pAStream = avformat_new_stream(g_pContainer, g_pACodec); |
110 #else |
|
111 g_pAStream = av_new_stream(g_pContainer, 1); |
|
112 #endif |
|
113 if(!g_pAStream) |
152 if(!g_pAStream) |
114 { |
153 { |
115 Log("Could not allocate audio stream\n"); |
154 Log("Could not allocate audio stream\n"); |
116 return; |
155 return; |
117 } |
156 } |
125 // put parameters |
164 // put parameters |
126 g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16; |
165 g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16; |
127 g_pAudio->sample_rate = g_Frequency; |
166 g_pAudio->sample_rate = g_Frequency; |
128 g_pAudio->channels = g_Channels; |
167 g_pAudio->channels = g_Channels; |
129 |
168 |
|
169 // set time base as invers of sample rate |
|
170 g_pAudio->time_base.den = g_pAStream->time_base.den = g_Frequency; |
|
171 g_pAudio->time_base.num = g_pAStream->time_base.num = 1; |
|
172 |
130 // set quality |
173 // set quality |
131 g_pAudio->bit_rate = 160000; |
174 g_pAudio->bit_rate = 160000; |
132 |
175 |
133 // for codecs that support variable bitrate use it, it should be better |
176 // for codecs that support variable bitrate use it, it should be better |
134 g_pAudio->flags |= CODEC_FLAG_QSCALE; |
177 g_pAudio->flags |= AV_CODEC_FLAG_QSCALE; |
135 g_pAudio->global_quality = 1*FF_QP2LAMBDA; |
178 g_pAudio->global_quality = 1*FF_QP2LAMBDA; |
136 |
179 |
137 // some formats want stream headers to be separate |
180 // some formats want stream headers to be separate |
138 if (g_pFormat->flags & AVFMT_GLOBALHEADER) |
181 if (g_pFormat->flags & AVFMT_GLOBALHEADER) |
139 g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER; |
182 g_pAudio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; |
140 |
183 |
141 // open it |
184 // open it |
142 #if LIBAVCODEC_VERSION_MAJOR >= 53 |
|
143 if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0) |
185 if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0) |
144 #else |
|
145 if (avcodec_open(g_pAudio, g_pACodec) < 0) |
|
146 #endif |
|
147 { |
186 { |
148 Log("Could not open audio codec %s\n", g_pACodec->long_name); |
187 Log("Could not open audio codec %s\n", g_pACodec->long_name); |
149 return; |
188 return; |
150 } |
189 } |
151 |
190 |
152 #if LIBAVCODEC_VERSION_MAJOR >= 54 |
191 #if LIBAVCODEC_VERSION_MAJOR >= 54 |
153 if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) |
192 if (g_pACodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) |
154 #else |
193 #else |
155 if (g_pAudio->frame_size == 0) |
194 if (g_pAudio->frame_size == 0) |
156 #endif |
195 #endif |
157 g_NumSamples = 4096; |
196 g_NumSamples = 4096; |
158 else |
197 else |
159 g_NumSamples = g_pAudio->frame_size; |
198 g_NumSamples = g_pAudio->frame_size; |
160 g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t)); |
199 g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t)); |
161 g_pAFrame = avcodec_alloc_frame(); |
200 g_pAFrame = av_frame_alloc(); |
162 if (!g_pAFrame) |
201 if (!g_pAFrame) |
163 { |
202 { |
164 Log("Could not allocate frame\n"); |
203 Log("Could not allocate frame\n"); |
165 return; |
204 return; |
166 } |
205 } |
170 static int WriteAudioFrame() |
209 static int WriteAudioFrame() |
171 { |
210 { |
172 if (!g_pAStream) |
211 if (!g_pAStream) |
173 return 0; |
212 return 0; |
174 |
213 |
175 AVPacket Packet = { 0 }; |
214 AVPacket Packet; |
176 av_init_packet(&Packet); |
215 av_init_packet(&Packet); |
|
216 Packet.data = NULL; |
|
217 Packet.size = 0; |
177 |
218 |
178 int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile); |
219 int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile); |
179 |
220 |
180 #if LIBAVCODEC_VERSION_MAJOR >= 53 |
221 #if LIBAVCODEC_VERSION_MAJOR >= 53 |
181 AVFrame* pFrame = NULL; |
222 AVFrame* pFrame = NULL; |
190 int got_packet; |
231 int got_packet; |
191 if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0) |
232 if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0) |
192 return FatalError("avcodec_encode_audio2 failed"); |
233 return FatalError("avcodec_encode_audio2 failed"); |
193 if (!got_packet) |
234 if (!got_packet) |
194 return 0; |
235 return 0; |
|
236 |
|
237 av_packet_rescale_ts(&Packet, g_pAudio->time_base, g_pAStream->time_base); |
195 #else |
238 #else |
196 if (NumSamples == 0) |
239 if (NumSamples == 0) |
197 return 0; |
240 return 0; |
198 int BufferSize = OUTBUFFER_SIZE; |
241 int BufferSize = OUTBUFFER_SIZE; |
199 if (g_pAudio->frame_size == 0) |
242 if (g_pAudio->frame_size == 0) |
215 } |
258 } |
216 |
259 |
217 // add a video output stream |
260 // add a video output stream |
218 static int AddVideoStream() |
261 static int AddVideoStream() |
219 { |
262 { |
220 #if LIBAVFORMAT_VERSION_MAJOR >= 53 |
|
221 g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec); |
263 g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec); |
222 #else |
|
223 g_pVStream = av_new_stream(g_pContainer, 0); |
|
224 #endif |
|
225 if (!g_pVStream) |
264 if (!g_pVStream) |
226 return FatalError("Could not allocate video stream"); |
265 return FatalError("Could not allocate video stream"); |
227 |
266 |
228 g_pVideo = g_pVStream->codec; |
267 g_pVideo = g_pVStream->codec; |
229 |
268 |
236 g_pVideo->height = g_Height & ~1; // make even |
275 g_pVideo->height = g_Height & ~1; // make even |
237 /* time base: this is the fundamental unit of time (in seconds) in terms |
276 /* time base: this is the fundamental unit of time (in seconds) in terms |
238 of which frame timestamps are represented. for fixed-fps content, |
277 of which frame timestamps are represented. for fixed-fps content, |
239 timebase should be 1/framerate and timestamp increments should be |
278 timebase should be 1/framerate and timestamp increments should be |
240 identically 1. */ |
279 identically 1. */ |
241 g_pVideo->time_base.den = g_Framerate.num; |
280 g_pVideo->time_base.den = g_pVStream->time_base.den = g_Framerate.num; |
242 g_pVideo->time_base.num = g_Framerate.den; |
281 g_pVideo->time_base.num = g_pVStream->time_base.num = g_Framerate.den; |
243 //g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */ |
282 |
244 g_pVideo->pix_fmt = PIX_FMT_YUV420P; |
283 g_pVideo->pix_fmt = AV_PIX_FMT_YUV420P; |
245 |
284 |
246 // set quality |
285 // set quality |
247 if (g_VQuality > 100) |
286 if (g_VQuality > 100) |
248 g_pVideo->bit_rate = g_VQuality; |
287 g_pVideo->bit_rate = g_VQuality; |
249 else |
288 else |
250 { |
289 { |
251 g_pVideo->flags |= CODEC_FLAG_QSCALE; |
290 g_pVideo->flags |= AV_CODEC_FLAG_QSCALE; |
252 g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA; |
291 g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA; |
253 } |
292 } |
254 |
293 |
255 // some formats want stream headers to be separate |
294 // some formats want stream headers to be separate |
256 if (g_pFormat->flags & AVFMT_GLOBALHEADER) |
295 if (g_pFormat->flags & AVFMT_GLOBALHEADER) |
257 g_pVideo->flags |= CODEC_FLAG_GLOBAL_HEADER; |
296 g_pVideo->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; |
258 |
297 |
259 #if LIBAVCODEC_VERSION_MAJOR < 53 |
298 #if LIBAVCODEC_VERSION_MAJOR < 53 |
260 // for some versions of ffmpeg x264 options must be set explicitly |
299 // for some versions of ffmpeg x264 options must be set explicitly |
261 if (strcmp(g_pVCodec->name, "libx264") == 0) |
300 if (strcmp(g_pVCodec->name, "libx264") == 0) |
262 { |
301 { |
286 g_pVideo->weighted_p_pred = 2; |
325 g_pVideo->weighted_p_pred = 2; |
287 } |
326 } |
288 #endif |
327 #endif |
289 |
328 |
290 // open the codec |
329 // open the codec |
291 #if LIBAVCODEC_VERSION_MAJOR >= 53 |
330 if (avcodec_open2(g_pVideo, g_pVCodec, NULL) < 0) |
292 AVDictionary* pDict = NULL; |
|
293 if (strcmp(g_pVCodec->name, "libx264") == 0) |
|
294 av_dict_set(&pDict, "preset", "medium", 0); |
|
295 |
|
296 if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0) |
|
297 #else |
|
298 if (avcodec_open(g_pVideo, g_pVCodec) < 0) |
|
299 #endif |
|
300 return FatalError("Could not open video codec %s", g_pVCodec->long_name); |
331 return FatalError("Could not open video codec %s", g_pVCodec->long_name); |
301 |
332 |
302 g_pVFrame = avcodec_alloc_frame(); |
333 g_pVFrame = av_frame_alloc(); |
303 if (!g_pVFrame) |
334 if (!g_pVFrame) |
304 return FatalError("Could not allocate frame"); |
335 return FatalError("Could not allocate frame"); |
305 |
336 |
|
337 g_pVFrame->width = g_Width; |
|
338 g_pVFrame->height = g_Height; |
|
339 g_pVFrame->format = AV_PIX_FMT_YUV420P; |
306 g_pVFrame->linesize[0] = g_Width; |
340 g_pVFrame->linesize[0] = g_Width; |
307 g_pVFrame->linesize[1] = g_Width/2; |
341 g_pVFrame->linesize[1] = g_Width/2; |
308 g_pVFrame->linesize[2] = g_Width/2; |
342 g_pVFrame->linesize[2] = g_Width/2; |
309 g_pVFrame->linesize[3] = 0; |
343 g_pVFrame->linesize[3] = 0; |
310 return 0; |
344 return 0; |
315 double AudioTime, VideoTime; |
349 double AudioTime, VideoTime; |
316 int ret; |
350 int ret; |
317 // write interleaved audio frame |
351 // write interleaved audio frame |
318 if (g_pAStream) |
352 if (g_pAStream) |
319 { |
353 { |
320 VideoTime = (double)g_pVStream->pts.val*g_pVStream->time_base.num/g_pVStream->time_base.den; |
354 VideoTime = (double)g_pVFrame->pts * g_pVStream->time_base.num/g_pVStream->time_base.den; |
321 do |
355 do |
322 { |
356 { |
323 AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den; |
357 AudioTime = (double)g_pAFrame->pts * g_pAStream->time_base.num/g_pAStream->time_base.den; |
324 ret = WriteAudioFrame(); |
358 ret = WriteAudioFrame(); |
325 } |
359 } |
326 while (AudioTime < VideoTime && ret); |
360 while (AudioTime < VideoTime && ret); |
327 if (ret < 0) |
361 if (ret < 0) |
328 return ret; |
362 return ret; |
349 if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) |
384 if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) |
350 return FatalError("Error while writing video frame"); |
385 return FatalError("Error while writing video frame"); |
351 return 0; |
386 return 0; |
352 } |
387 } |
353 else |
388 else |
|
389 #endif |
354 { |
390 { |
355 #if LIBAVCODEC_VERSION_MAJOR >= 54 |
391 #if LIBAVCODEC_VERSION_MAJOR >= 54 |
356 int got_packet; |
392 int got_packet; |
357 if (avcodec_encode_video2(g_pVideo, &Packet, pFrame, &got_packet) < 0) |
393 if (avcodec_encode_video2(g_pVideo, &Packet, pFrame, &got_packet) < 0) |
358 return FatalError("avcodec_encode_video2 failed"); |
394 return FatalError("avcodec_encode_video2 failed"); |
359 if (!got_packet) |
395 if (!got_packet) |
360 return 0; |
396 return 0; |
361 |
397 |
362 if (Packet.pts != AV_NOPTS_VALUE) |
398 av_packet_rescale_ts(&Packet, g_pVideo->time_base, g_pVStream->time_base); |
363 Packet.pts = av_rescale_q(Packet.pts, g_pVideo->time_base, g_pVStream->time_base); |
|
364 if (Packet.dts != AV_NOPTS_VALUE) |
|
365 Packet.dts = av_rescale_q(Packet.dts, g_pVideo->time_base, g_pVStream->time_base); |
|
366 #else |
399 #else |
367 Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame); |
400 Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame); |
368 if (Packet.size < 0) |
401 if (Packet.size < 0) |
369 return FatalError("avcodec_encode_video failed"); |
402 return FatalError("avcodec_encode_video failed"); |
370 if (Packet.size == 0) |
403 if (Packet.size == 0) |
494 |
527 |
495 AVWRAP_DECL int AVWrapper_Close() |
528 AVWRAP_DECL int AVWrapper_Close() |
496 { |
529 { |
497 int ret; |
530 int ret; |
498 // output buffered frames |
531 // output buffered frames |
499 if (g_pVCodec->capabilities & CODEC_CAP_DELAY) |
532 if (g_pVCodec->capabilities & AV_CODEC_CAP_DELAY) |
500 { |
533 { |
501 do |
534 do |
502 ret = WriteFrame(NULL); |
535 ret = WriteFrame(NULL); |
503 while (ret >= 0); |
536 while (ret > 0); |
504 if (ret < 0) |
537 if (ret < 0) |
505 return ret; |
538 return ret; |
506 } |
539 } |
507 // output any remaining audio |
540 // output any remaining audio |
508 do |
541 do |
509 { |
542 { |
510 ret = WriteAudioFrame(); |
543 ret = WriteAudioFrame(); |
511 } |
544 } |
512 while(ret >= 0); |
545 while(ret > 0); |
513 if (ret < 0) |
546 if (ret < 0) |
514 return ret; |
547 return ret; |
515 |
548 |
516 // write the trailer, if any. |
549 // write the trailer, if any. |
517 av_write_trailer(g_pContainer); |
550 av_write_trailer(g_pContainer); |