Mercurial > projects > hoofbaby
comparison src/impl/hoofbaby/app/transcode.d @ 9:05c88622db6b default tip
- Adhoc transcoder now doesn't rely on Platinum
- Moved the adhoc transcoder to the main source tree; it can be moved back into test once it's more stable
author | fraserofthenight |
---|---|
date | Tue, 14 Jul 2009 22:04:05 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
8:71ebad05f542 | 9:05c88622db6b |
---|---|
1 /** | |
2 * Hoofbaby -- http://www.dsource.org/projects/hoofbaby | |
3 * Copyright (C) 2009 Robert Fraser | |
4 * | |
5 * This program is free software; you can redistribute it andor | |
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. | |
9 * | |
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. | |
14 */ | |
15 | |
16 module hoofbaby.app.transcode; | |
17 | |
18 import NONE_1 = tango.stdc.stdarg; // Must be linked in to prevent strange linker errors | |
19 debug import NONE_2 = tango.core.stacktrace.TraceExceptions; | |
20 import NONE_3 = hoofbaby.codec.libav.mingw; | |
21 | |
22 import hoofbaby.app.libs; | |
23 import hoofbaby.codec.decoder; | |
24 import hoofbaby.codec.encoder; | |
25 | |
26 public int main(char[][] args) | |
27 { | |
28 initLibs(); | |
29 scope Decoder dec = new Decoder("../../ref/testv-h264-vorbis-ass.mkv"); | |
30 scope Encoder enc = new Encoder("trans.wmv"); | |
31 // WORKAREA check ffmpeg.c:1742 | |
32 return 0; | |
33 } | |
34 | |
35 /+ | |
36 | |
37 import Math = tango.math.Math; | |
38 import hoofbaby.codec.libav.avutil; | |
39 import hoofbaby.codec.libav.avcodec; | |
40 import hoofbaby.codec.libav.avformat; | |
41 | |
42 private const int STREAM_FRAME_RATE = 25; | |
43 private const double STREAM_DURATION = 5.0; | |
44 private const int STREAM_NB_FRAMES = (cast(int) (STREAM_DURATION * STREAM_FRAME_RATE)); | |
45 private const int WIDTH = 352; | |
46 private const int HEIGHT = 288; | |
47 private const int SAMPLE_RATE = 44100; | |
48 private int AUDIO_FRAME_SIZE; | |
49 | |
50 private int frameCount = 0; | |
51 private double audioCount = 0.0; | |
52 private double audioIncr = 2 * Math.PI * 110.0 / SAMPLE_RATE; | |
53 private double audioIncr2 = 2 * Math.PI * 110.0 / SAMPLE_RATE / SAMPLE_RATE; | |
54 | |
55 private AVFrame* generatePicture(AVFrame* pict, int width, int height) | |
56 { | |
57 int x, y, i; | |
58 i = frameCount; | |
59 | |
60 /* Y */ | |
61 for(y = 0; y < height; y++) | |
62 { | |
63 for(x = 0; x < width; x++) | |
64 { | |
65 pict.data[0][y * pict.linesize[0] + x] = x + y + i * 3; | |
66 } | |
67 } | |
68 | |
69 /* Cb and Cr */ | |
70 for(y = 0; y < height / 2; y++) | |
71 { | |
72 for(x = 0; x < width / 2; x++) | |
73 { | |
74 pict.data[1][y * pict.linesize[1] + x] = 128 + y + i * 2; | |
75 pict.data[2][y * pict.linesize[2] + x] = 64 + x + i * 5; | |
76 } | |
77 } | |
78 | |
79 return pict; | |
80 } | |
81 | |
82 private short* generateAudio(short* samples) | |
83 { | |
84 int j, i, v; | |
85 short *q; | |
86 | |
87 q = samples; | |
88 for(j = 0; j < AUDIO_FRAME_SIZE; j++) | |
89 { | |
90 v = cast(int)(Math.sin(audioCount) * 10000); | |
91 for(i = 0; i < 2; i++) // 2 is number of channels | |
92 *q++ = v; | |
93 audioCount += audioIncr; | |
94 audioIncr += audioIncr2; | |
95 } | |
96 | |
97 return samples; | |
98 } | |
99 | |
100 public int main(char[][] args) | |
101 { | |
102 initLibs(); | |
103 scope Encoder enc = new Encoder("biff_happy.wmv"); | |
104 AUDIO_FRAME_SIZE = enc.audioContext.frame_size; | |
105 | |
106 // Allocate a video frame and audio buffer to store stuff | |
107 AVFrame* frame = avpicture_alloc(PIX_FMT_YUV420P, WIDTH, HEIGHT); | |
108 assert(frame !is null, "Could not allocate frame"); | |
109 scope(exit) if(frame) av_free(frame); | |
110 short* samples = cast(short*) av_malloc(AUDIO_FRAME_SIZE * 2 * 2); // AUDIO_FRAME_SIZE * 2 * number of channels | |
111 assert(frame !is null, "Could not allocate samples"); | |
112 scope(exit) if(samples) av_free(samples); | |
113 | |
114 // Write header | |
115 enc.writeHeader(); | |
116 | |
117 while(true) | |
118 { | |
119 double audio_pts = cast(double) enc.audioStream.pts.val * enc.audioStream.time_base.num / enc.audioStream.time_base.den; | |
120 double video_pts = cast(double) enc.videoStream.pts.val * enc.videoStream.time_base.num / enc.videoStream.time_base.den; | |
121 | |
122 if(audio_pts >= STREAM_DURATION && video_pts >= STREAM_DURATION) | |
123 break; | |
124 | |
125 // Write interleaved audio & video | |
126 if(audio_pts < video_pts) | |
127 { | |
128 enc.writeAudioFrame(generateAudio(samples)); | |
129 } | |
130 else | |
131 { | |
132 if(frameCount >= STREAM_NB_FRAMES) | |
133 { | |
134 // no more frame to compress. The codec has a latency of a few | |
135 // frames if using B frames, so we get the last frames by | |
136 // passing the same picture again | |
137 } | |
138 else | |
139 { | |
140 generatePicture(frame, WIDTH, HEIGHT); | |
141 } | |
142 | |
143 enc.writeVideoFrame(frame); | |
144 frameCount++; | |
145 } | |
146 } | |
147 | |
148 // Write trailer | |
149 enc.writeTrailer(); | |
150 | |
151 return 0; | |
152 } | |
153 +/ |