author | Stepan777 <stepik-777@mail.ru> |
Tue, 12 Jun 2012 17:20:27 +0400 | |
changeset 7238 | 313b2ecc4441 |
parent 7235 | baa69bd025d9 |
child 7280 | fd707afbc3a2 |
permissions | -rw-r--r-- |
7180 | 1 |
|
2 |
#include <stdlib.h> |
|
3 |
#include <stdio.h> |
|
4 |
#include <string.h> |
|
5 |
#include <stdarg.h> |
|
6 |
#include "libavformat/avformat.h" |
|
7 |
||
8 |
static AVFormatContext* g_pContainer; |
|
9 |
static AVOutputFormat* g_pFormat; |
|
10 |
static AVStream* g_pAStream; |
|
11 |
static AVStream* g_pVStream; |
|
12 |
static AVFrame* g_pAFrame; |
|
13 |
static AVFrame* g_pVFrame; |
|
14 |
static AVCodec* g_pACodec; |
|
15 |
static AVCodec* g_pVCodec; |
|
16 |
static AVCodecContext* g_pAudio; |
|
17 |
static AVCodecContext* g_pVideo; |
|
18 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
19 |
static int g_Width, g_Height; |
7180 | 20 |
static int g_Frequency, g_Channels; |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
21 |
static int g_VQuality, g_AQuality; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
22 |
static AVRational g_Framerate; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
23 |
static const char* g_pPreset; |
7180 | 24 |
|
25 |
static FILE* g_pSoundFile; |
|
26 |
static int16_t* g_pSamples; |
|
27 |
static int g_NumSamples; |
|
28 |
||
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
29 |
static char g_Filename[1024]; |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
30 |
|
7180 | 31 |
/* |
32 |
Initially I wrote code for latest ffmpeg, but on Linux (Ubuntu) |
|
33 |
only older version is available from repository. That's why you see here |
|
34 |
all of this #if LIBAVCODEC_VERSION_MAJOR < 54. |
|
35 |
Actually, it may be possible to remove code for newer version |
|
36 |
and use only code for older version. |
|
37 |
*/ |
|
38 |
||
39 |
#if LIBAVCODEC_VERSION_MAJOR < 54 |
|
40 |
#define OUTBUFFER_SIZE 200000 |
|
41 |
static uint8_t g_OutBuffer[OUTBUFFER_SIZE]; |
|
42 |
#endif |
|
43 |
||
44 |
// pointer to function from hwengine (uUtils.pas) |
|
45 |
static void (*AddFileLogRaw)(const char* pString); |
|
46 |
||
47 |
static void FatalError(const char* pFmt, ...) |
|
48 |
{ |
|
49 |
const char Buffer[1024]; |
|
50 |
va_list VaArgs; |
|
51 |
||
52 |
va_start(VaArgs, pFmt); |
|
53 |
vsnprintf(Buffer, 1024, pFmt, VaArgs); |
|
54 |
va_end(VaArgs); |
|
55 |
||
56 |
AddFileLogRaw("Error in av-wrapper: "); |
|
57 |
AddFileLogRaw(Buffer); |
|
58 |
AddFileLogRaw("\n"); |
|
59 |
exit(1); |
|
60 |
} |
|
61 |
||
62 |
// Function to be called from libav for logging. |
|
63 |
// Note: libav can call LogCallback from different threads |
|
64 |
// (there is mutex in AddFileLogRaw). |
|
65 |
static void LogCallback(void* p, int Level, const char* pFmt, va_list VaArgs) |
|
66 |
{ |
|
67 |
const char Buffer[1024]; |
|
68 |
||
69 |
vsnprintf(Buffer, 1024, pFmt, VaArgs); |
|
70 |
AddFileLogRaw(Buffer); |
|
71 |
} |
|
72 |
||
73 |
static void Log(const char* pFmt, ...) |
|
74 |
{ |
|
75 |
const char Buffer[1024]; |
|
76 |
va_list VaArgs; |
|
77 |
||
78 |
va_start(VaArgs, pFmt); |
|
79 |
vsnprintf(Buffer, 1024, pFmt, VaArgs); |
|
80 |
va_end(VaArgs); |
|
81 |
||
82 |
AddFileLogRaw(Buffer); |
|
83 |
} |
|
84 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
85 |
static void AddAudioStream() |
7180 | 86 |
{ |
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
87 |
#if LIBAVFORMAT_VERSION_MAJOR >= 54 |
7180 | 88 |
g_pAStream = avformat_new_stream(g_pContainer, g_pACodec); |
89 |
#else |
|
90 |
g_pAStream = av_new_stream(g_pContainer, 1); |
|
91 |
#endif |
|
92 |
if(!g_pAStream) |
|
93 |
FatalError("Could not allocate audio stream"); |
|
94 |
g_pAStream->id = 1; |
|
95 |
||
96 |
g_pAudio = g_pAStream->codec; |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
97 |
|
7180 | 98 |
avcodec_get_context_defaults3(g_pAudio, g_pACodec); |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
99 |
g_pAudio->codec_id = g_pACodec->id; |
7180 | 100 |
|
101 |
// put parameters |
|
102 |
g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16; |
|
103 |
g_pAudio->sample_rate = g_Frequency; |
|
104 |
g_pAudio->channels = g_Channels; |
|
105 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
106 |
// set quality |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
107 |
if (g_AQuality > 100) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
108 |
g_pAudio->bit_rate = g_AQuality; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
109 |
else |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
110 |
{ |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
111 |
g_pAudio->flags |= CODEC_FLAG_QSCALE; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
112 |
g_pAudio->global_quality = g_AQuality*FF_QP2LAMBDA; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
113 |
} |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
114 |
|
7180 | 115 |
// some formats want stream headers to be separate |
116 |
if (g_pFormat->flags & AVFMT_GLOBALHEADER) |
|
117 |
g_pAudio->flags |= CODEC_FLAG_GLOBAL_HEADER; |
|
118 |
||
119 |
// open it |
|
120 |
if (avcodec_open2(g_pAudio, g_pACodec, NULL) < 0) |
|
121 |
FatalError("Could not open audio codec %s", g_pACodec->long_name); |
|
122 |
||
123 |
#if LIBAVCODEC_VERSION_MAJOR >= 54 |
|
124 |
if (g_pACodec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) |
|
125 |
#else |
|
126 |
if (g_pAudio->frame_size == 0) |
|
127 |
#endif |
|
128 |
g_NumSamples = 4096; |
|
129 |
else |
|
130 |
g_NumSamples = g_pAudio->frame_size; |
|
131 |
g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t)); |
|
132 |
g_pAFrame = avcodec_alloc_frame(); |
|
133 |
if (!g_pAFrame) |
|
134 |
FatalError("Could not allocate frame"); |
|
135 |
} |
|
136 |
||
137 |
// returns non-zero if there is more sound |
|
138 |
static int WriteAudioFrame() |
|
139 |
{ |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
140 |
if (!g_pAStream) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
141 |
return 0; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
142 |
|
7180 | 143 |
AVPacket Packet = { 0 }; |
144 |
av_init_packet(&Packet); |
|
145 |
||
146 |
int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile); |
|
147 |
||
148 |
#if LIBAVCODEC_VERSION_MAJOR >= 54 |
|
149 |
AVFrame* pFrame = NULL; |
|
150 |
if (NumSamples > 0) |
|
151 |
{ |
|
152 |
g_pAFrame->nb_samples = NumSamples; |
|
153 |
avcodec_fill_audio_frame(g_pAFrame, g_Channels, AV_SAMPLE_FMT_S16, |
|
154 |
(uint8_t*)g_pSamples, NumSamples*2*g_Channels, 1); |
|
155 |
pFrame = g_pAFrame; |
|
156 |
} |
|
157 |
// when NumSamples == 0 we still need to call encode_audio2 to flush |
|
158 |
int got_packet; |
|
159 |
if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0) |
|
160 |
FatalError("avcodec_encode_audio2 failed"); |
|
161 |
if (!got_packet) |
|
162 |
return 0; |
|
163 |
#else |
|
164 |
if (NumSamples == 0) |
|
165 |
return 0; |
|
166 |
int BufferSize = OUTBUFFER_SIZE; |
|
167 |
if (g_pAudio->frame_size == 0) |
|
168 |
BufferSize = NumSamples*g_Channels*2; |
|
169 |
Packet.size = avcodec_encode_audio(g_pAudio, g_OutBuffer, BufferSize, g_pSamples); |
|
170 |
if (Packet.size == 0) |
|
171 |
return 1; |
|
172 |
if (g_pAudio->coded_frame && g_pAudio->coded_frame->pts != AV_NOPTS_VALUE) |
|
173 |
Packet.pts = av_rescale_q(g_pAudio->coded_frame->pts, g_pAudio->time_base, g_pAStream->time_base); |
|
174 |
Packet.flags |= AV_PKT_FLAG_KEY; |
|
175 |
Packet.data = g_OutBuffer; |
|
176 |
#endif |
|
177 |
||
178 |
// Write the compressed frame to the media file. |
|
179 |
Packet.stream_index = g_pAStream->index; |
|
180 |
if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) |
|
181 |
FatalError("Error while writing audio frame"); |
|
182 |
return 1; |
|
183 |
} |
|
184 |
||
185 |
// add a video output stream |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
186 |
static void AddVideoStream() |
7180 | 187 |
{ |
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
188 |
#if LIBAVFORMAT_VERSION_MAJOR >= 54 |
7180 | 189 |
g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec); |
190 |
#else |
|
191 |
g_pVStream = av_new_stream(g_pContainer, 0); |
|
192 |
#endif |
|
193 |
if (!g_pVStream) |
|
194 |
FatalError("Could not allocate video stream"); |
|
195 |
||
196 |
g_pVideo = g_pVStream->codec; |
|
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
197 |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
198 |
avcodec_get_context_defaults3(g_pVideo, g_pVCodec); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
199 |
g_pVideo->codec_id = g_pVCodec->id; |
7180 | 200 |
|
201 |
// put parameters |
|
202 |
// resolution must be a multiple of two |
|
203 |
g_pVideo->width = g_Width; |
|
204 |
g_pVideo->height = g_Height; |
|
205 |
/* time base: this is the fundamental unit of time (in seconds) in terms |
|
206 |
of which frame timestamps are represented. for fixed-fps content, |
|
207 |
timebase should be 1/framerate and timestamp increments should be |
|
208 |
identically 1. */ |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
209 |
g_pVideo->time_base.den = g_Framerate.num; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
210 |
g_pVideo->time_base.num = g_Framerate.den; |
7180 | 211 |
//g_pVideo->gop_size = 12; /* emit one intra frame every twelve frames at most */ |
212 |
g_pVideo->pix_fmt = PIX_FMT_YUV420P; |
|
213 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
214 |
// set quality |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
215 |
if (g_VQuality > 100) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
216 |
g_pVideo->bit_rate = g_VQuality; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
217 |
else |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
218 |
{ |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
219 |
g_pVideo->flags |= CODEC_FLAG_QSCALE; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
220 |
g_pVideo->global_quality = g_VQuality*FF_QP2LAMBDA; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
221 |
} |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
222 |
|
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
223 |
AVDictionary* pDict = NULL; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
224 |
if (strcmp(g_pVCodec->name, "libx264") == 0) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
225 |
av_dict_set(&pDict, "preset", g_pPreset, 0); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
226 |
|
7180 | 227 |
// some formats want stream headers to be separate |
228 |
if (g_pFormat->flags & AVFMT_GLOBALHEADER) |
|
229 |
g_pVideo->flags |= CODEC_FLAG_GLOBAL_HEADER; |
|
230 |
||
231 |
// open the codec |
|
232 |
if (avcodec_open2(g_pVideo, g_pVCodec, &pDict) < 0) |
|
233 |
FatalError("Could not open video codec %s", g_pVCodec->long_name); |
|
234 |
||
235 |
g_pVFrame = avcodec_alloc_frame(); |
|
236 |
if (!g_pVFrame) |
|
237 |
FatalError("Could not allocate frame"); |
|
238 |
||
239 |
g_pVFrame->linesize[0] = g_Width; |
|
240 |
g_pVFrame->linesize[1] = g_Width/2; |
|
241 |
g_pVFrame->linesize[2] = g_Width/2; |
|
242 |
g_pVFrame->linesize[3] = 0; |
|
243 |
} |
|
244 |
||
245 |
static int WriteFrame( AVFrame* pFrame ) |
|
246 |
{ |
|
247 |
double AudioTime, VideoTime; |
|
248 |
||
249 |
// write interleaved audio frame |
|
250 |
if (g_pAStream) |
|
251 |
{ |
|
252 |
VideoTime = (double)g_pVStream->pts.val*g_pVStream->time_base.num/g_pVStream->time_base.den; |
|
253 |
do |
|
254 |
AudioTime = (double)g_pAStream->pts.val*g_pAStream->time_base.num/g_pAStream->time_base.den; |
|
255 |
while (AudioTime < VideoTime && WriteAudioFrame()); |
|
256 |
} |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
257 |
|
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
258 |
if (!g_pVStream) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
259 |
return 0; |
7180 | 260 |
|
261 |
AVPacket Packet; |
|
262 |
av_init_packet(&Packet); |
|
263 |
Packet.data = NULL; |
|
264 |
Packet.size = 0; |
|
265 |
||
266 |
g_pVFrame->pts++; |
|
267 |
if (g_pFormat->flags & AVFMT_RAWPICTURE) |
|
268 |
{ |
|
269 |
/* raw video case. The API will change slightly in the near |
|
270 |
future for that. */ |
|
271 |
Packet.flags |= AV_PKT_FLAG_KEY; |
|
272 |
Packet.stream_index = g_pVStream->index; |
|
273 |
Packet.data = (uint8_t*)pFrame; |
|
274 |
Packet.size = sizeof(AVPicture); |
|
275 |
||
276 |
if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) |
|
277 |
FatalError("Error while writing video frame"); |
|
278 |
return 0; |
|
279 |
} |
|
280 |
else |
|
281 |
{ |
|
282 |
#if LIBAVCODEC_VERSION_MAJOR >= 54 |
|
283 |
int got_packet; |
|
284 |
if (avcodec_encode_video2(g_pVideo, &Packet, pFrame, &got_packet) < 0) |
|
285 |
FatalError("avcodec_encode_video2 failed"); |
|
286 |
if (!got_packet) |
|
287 |
return 0; |
|
288 |
||
289 |
if (Packet.pts != AV_NOPTS_VALUE) |
|
290 |
Packet.pts = av_rescale_q(Packet.pts, g_pVideo->time_base, g_pVStream->time_base); |
|
291 |
if (Packet.dts != AV_NOPTS_VALUE) |
|
292 |
Packet.dts = av_rescale_q(Packet.dts, g_pVideo->time_base, g_pVStream->time_base); |
|
293 |
#else |
|
294 |
Packet.size = avcodec_encode_video(g_pVideo, g_OutBuffer, OUTBUFFER_SIZE, pFrame); |
|
295 |
if (Packet.size < 0) |
|
296 |
FatalError("avcodec_encode_video failed"); |
|
297 |
if (Packet.size == 0) |
|
298 |
return 0; |
|
299 |
||
300 |
if( g_pVideo->coded_frame->pts != AV_NOPTS_VALUE) |
|
301 |
Packet.pts = av_rescale_q(g_pVideo->coded_frame->pts, g_pVideo->time_base, g_pVStream->time_base); |
|
302 |
if( g_pVideo->coded_frame->key_frame ) |
|
303 |
Packet.flags |= AV_PKT_FLAG_KEY; |
|
304 |
Packet.data = g_OutBuffer; |
|
305 |
#endif |
|
306 |
// write the compressed frame in the media file |
|
307 |
Packet.stream_index = g_pVStream->index; |
|
308 |
if (av_interleaved_write_frame(g_pContainer, &Packet) != 0) |
|
309 |
FatalError("Error while writing video frame"); |
|
310 |
||
311 |
return 1; |
|
312 |
} |
|
313 |
} |
|
314 |
||
315 |
void AVWrapper_WriteFrame(uint8_t* pY, uint8_t* pCb, uint8_t* pCr) |
|
316 |
{ |
|
317 |
g_pVFrame->data[0] = pY; |
|
318 |
g_pVFrame->data[1] = pCb; |
|
319 |
g_pVFrame->data[2] = pCr; |
|
320 |
WriteFrame(g_pVFrame); |
|
321 |
} |
|
322 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
323 |
void AVWrapper_Init( |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
324 |
void (*pAddFileLogRaw)(const char*), |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
325 |
const char* pFilename, |
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
326 |
const char* pFinalFilename, |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
327 |
const char* pSoundFile, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
328 |
const char* pFormatName, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
329 |
const char* pVCodecName, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
330 |
const char* pACodecName, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
331 |
const char* pVPreset, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
332 |
int Width, int Height, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
333 |
int FramerateNum, int FramerateDen, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
334 |
int Frequency, int Channels, |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
335 |
int VQuality, int AQuality) |
7180 | 336 |
{ |
337 |
AddFileLogRaw = pAddFileLogRaw; |
|
338 |
av_log_set_callback( &LogCallback ); |
|
339 |
||
340 |
g_Width = Width; |
|
341 |
g_Height = Height; |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
342 |
g_Framerate.num = FramerateNum; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
343 |
g_Framerate.den = FramerateDen; |
7180 | 344 |
g_Frequency = Frequency; |
345 |
g_Channels = Channels; |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
346 |
g_VQuality = VQuality; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
347 |
g_AQuality = AQuality; |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
348 |
g_pPreset = pVPreset; |
7180 | 349 |
|
350 |
// initialize libav and register all codecs and formats |
|
351 |
av_register_all(); |
|
352 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
353 |
// find format |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
354 |
g_pFormat = av_guess_format(pFormatName, NULL, NULL); |
7180 | 355 |
if (!g_pFormat) |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
356 |
FatalError("Format \"%s\" was not found", pFormatName); |
7180 | 357 |
|
358 |
// allocate the output media context |
|
359 |
g_pContainer = avformat_alloc_context(); |
|
360 |
if (!g_pContainer) |
|
361 |
FatalError("Could not allocate output context"); |
|
362 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
363 |
g_pContainer->oformat = g_pFormat; |
7180 | 364 |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
365 |
// append extesnion to filename |
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
366 |
char ext[16]; |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
367 |
strncpy(ext, g_pFormat->extensions, 16); |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
368 |
ext[15] = 0; |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
369 |
ext[strcspn(ext,",")] = 0; |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
370 |
snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext); |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
371 |
snprintf(g_Filename, sizeof(g_Filename), "%s.%s", pFinalFilename, ext); |
7180 | 372 |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
373 |
// find codecs |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
374 |
g_pVCodec = avcodec_find_encoder_by_name(pVCodecName); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
375 |
g_pACodec = avcodec_find_encoder_by_name(pACodecName); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
376 |
|
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
377 |
// add audio and video stream to container |
7180 | 378 |
g_pVStream = NULL; |
379 |
g_pAStream = NULL; |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
380 |
|
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
381 |
if (g_pVCodec) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
382 |
AddVideoStream(); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
383 |
else |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
384 |
Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName); |
7180 | 385 |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
386 |
if (g_pACodec) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
387 |
AddAudioStream(); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
388 |
else |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
389 |
Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
390 |
|
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
391 |
if (!g_pAStream && !g_pVStream) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
392 |
FatalError("No video, no audio, aborting..."); |
7180 | 393 |
|
394 |
if (g_pAStream) |
|
395 |
{ |
|
396 |
g_pSoundFile = fopen(pSoundFile, "rb"); |
|
397 |
if (!g_pSoundFile) |
|
398 |
FatalError("Could not open %s", pSoundFile); |
|
399 |
} |
|
400 |
||
401 |
// write format info to log |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
402 |
av_dump_format(g_pContainer, 0, g_pContainer->filename, 1); |
7180 | 403 |
|
404 |
// open the output file, if needed |
|
405 |
if (!(g_pFormat->flags & AVFMT_NOFILE)) |
|
406 |
{ |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
407 |
if (avio_open(&g_pContainer->pb, g_pContainer->filename, AVIO_FLAG_WRITE) < 0) |
7180 | 408 |
FatalError("Could not open output file (%s)", pFilename); |
409 |
} |
|
410 |
||
411 |
// write the stream header, if any |
|
412 |
avformat_write_header(g_pContainer, NULL); |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
413 |
|
7180 | 414 |
g_pVFrame->pts = -1; |
415 |
} |
|
416 |
||
417 |
void AVWrapper_Close() |
|
418 |
{ |
|
419 |
// output buffered frames |
|
420 |
if (g_pVCodec->capabilities & CODEC_CAP_DELAY) |
|
421 |
while( WriteFrame(NULL) ); |
|
422 |
// output any remaining audio |
|
423 |
while( WriteAudioFrame() ); |
|
424 |
||
425 |
// write the trailer, if any. |
|
426 |
av_write_trailer(g_pContainer); |
|
427 |
||
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
428 |
// close the output file |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
429 |
if (!(g_pFormat->flags & AVFMT_NOFILE)) |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
430 |
avio_close(g_pContainer->pb); |
7235
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
431 |
|
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
432 |
// move file to destination |
baa69bd025d9
1. Implement new page in frontend with options for video recording.
Stepan777 <stepik-777@mail.ru>
parents:
7198
diff
changeset
|
433 |
rename(g_pContainer->filename, g_Filename); |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
434 |
|
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
435 |
// free everything |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
436 |
if (g_pVStream) |
7180 | 437 |
{ |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
438 |
avcodec_close(g_pVideo); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
439 |
av_free(g_pVideo); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
440 |
av_free(g_pVStream); |
7180 | 441 |
av_free(g_pVFrame); |
442 |
} |
|
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
443 |
if (g_pAStream) |
7180 | 444 |
{ |
7198
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
445 |
avcodec_close(g_pAudio); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
446 |
av_free(g_pAudio); |
5debd5fe526e
1. Add IFDEFs for video recording
Stepan777 <stepik-777@mail.ru>
parents:
7180
diff
changeset
|
447 |
av_free(g_pAStream); |
7180 | 448 |
av_free(g_pAFrame); |
449 |
av_free(g_pSamples); |
|
450 |
fclose(g_pSoundFile); |
|
451 |
} |
|
452 |
||
453 |
av_free(g_pContainer); |
|
454 |
} |