Mercurial > mplayer.hg
annotate libmpcodecs/ae_lavc.c @ 15533:ddf15d233d58
Do not switch to audio tracks whose codec private data differs from the main audio track's as this will most likely result in messed up audio output. Patch by Michael Behrisch <list () behrisch ! de>
author | mosu |
---|---|
date | Sat, 21 May 2005 06:50:08 +0000 |
parents | 7cdc07507650 |
children | 6ff3379a0862 |
rev | line source |
---|---|
15234 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <inttypes.h> | |
15238 | 4 #include <unistd.h> |
15234 | 5 #include <string.h> |
15240 | 6 #include <sys/types.h> |
15234 | 7 #include "m_option.h" |
8 #include "../mp_msg.h" | |
9 #include "aviheader.h" | |
10 #include "ms_hdr.h" | |
11 #include "muxer.h" | |
12 #include "ae_lavc.h" | |
13 #include "help_mp.h" | |
14 #include "../config.h" | |
15 #include "../libaf/af_format.h" | |
16 #ifdef USE_LIBAVCODEC_SO | |
17 #include <ffmpeg/avcodec.h> | |
18 #else | |
19 #include "libavcodec/avcodec.h" | |
20 #endif | |
21 | |
22 static AVCodec *lavc_acodec; | |
23 static AVCodecContext *lavc_actx; | |
24 extern char *lavc_param_acodec; | |
25 extern int lavc_param_abitrate; | |
26 extern int lavc_param_atag; | |
27 extern int avcodec_inited; | |
28 static int compressed_frame_size = 0; | |
29 | |
30 static int bind_lavc(audio_encoder_t *encoder, muxer_stream_t *mux_a) | |
31 { | |
32 mux_a->wf = malloc(sizeof(WAVEFORMATEX)+lavc_actx->extradata_size+256); | |
33 mux_a->wf->wFormatTag = lavc_param_atag; | |
34 mux_a->wf->nChannels = lavc_actx->channels; | |
35 mux_a->wf->nSamplesPerSec = lavc_actx->sample_rate; | |
36 mux_a->wf->nAvgBytesPerSec = (lavc_actx->bit_rate / 8); | |
37 mux_a->h.dwRate = mux_a->wf->nAvgBytesPerSec; | |
38 if(lavc_actx->block_align) | |
39 mux_a->h.dwSampleSize = mux_a->h.dwScale = lavc_actx->block_align; | |
40 else | |
41 { | |
42 mux_a->h.dwScale = (mux_a->wf->nAvgBytesPerSec * lavc_actx->frame_size)/ mux_a->wf->nSamplesPerSec; /* for cbr */ | |
43 | |
44 if ((mux_a->wf->nAvgBytesPerSec * | |
45 lavc_actx->frame_size) % mux_a->wf->nSamplesPerSec) | |
46 { | |
47 mux_a->h.dwScale = lavc_actx->frame_size; | |
48 mux_a->h.dwRate = lavc_actx->sample_rate; | |
49 mux_a->h.dwSampleSize = 0; // Blocksize not constant | |
50 } | |
51 else | |
52 mux_a->h.dwSampleSize = mux_a->h.dwScale; | |
53 } | |
54 mux_a->wf->nBlockAlign = mux_a->h.dwScale; | |
55 mux_a->h.dwSuggestedBufferSize = (encoder->params.audio_preload*mux_a->wf->nAvgBytesPerSec)/1000; | |
56 mux_a->h.dwSuggestedBufferSize -= mux_a->h.dwSuggestedBufferSize % mux_a->wf->nBlockAlign; | |
57 | |
58 switch(lavc_param_atag) | |
59 { | |
60 case 0x11: /* imaadpcm */ | |
61 mux_a->wf->wBitsPerSample = 4; | |
62 mux_a->wf->cbSize = 2; | |
63 ((uint16_t*)mux_a->wf)[sizeof(WAVEFORMATEX)] = | |
64 ((lavc_actx->block_align - 4 * lavc_actx->channels) / (4 * lavc_actx->channels)) * 8 + 1; | |
65 break; | |
66 case 0x55: /* mp3 */ | |
67 mux_a->wf->cbSize = 12; | |
68 mux_a->wf->wBitsPerSample = 0; /* does not apply */ | |
69 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->wID = 1; | |
70 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->fdwFlags = 2; | |
71 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nBlockSize = mux_a->wf->nBlockAlign; | |
72 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nFramesPerBlock = 1; | |
73 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nCodecDelay = 0; | |
74 break; | |
75 default: | |
76 mux_a->wf->wBitsPerSample = 0; /* Unknown */ | |
77 if (lavc_actx->extradata && (lavc_actx->extradata_size > 0)) | |
78 { | |
15501
7cdc07507650
wrong memcpy of extradata; 10l to whomever wrote that broken code
nicodvb
parents:
15244
diff
changeset
|
79 memcpy(mux_a->wf+1, lavc_actx->extradata, lavc_actx->extradata_size); |
15234 | 80 mux_a->wf->cbSize = lavc_actx->extradata_size; |
81 } | |
82 else | |
83 mux_a->wf->cbSize = 0; | |
84 break; | |
85 } | |
86 | |
87 // Fix allocation | |
88 mux_a->wf = realloc(mux_a->wf, sizeof(WAVEFORMATEX)+mux_a->wf->cbSize); | |
89 | |
90 encoder->input_format = AF_FORMAT_S16_NE; | |
91 encoder->min_buffer_size = mux_a->h.dwSuggestedBufferSize; | |
92 encoder->max_buffer_size = mux_a->h.dwSuggestedBufferSize*2; | |
93 | |
94 return 1; | |
95 } | |
96 | |
97 static int encode_lavc(audio_encoder_t *encoder, uint8_t *dest, void *src, int size, int max_size) | |
98 { | |
99 int n; | |
100 n = avcodec_encode_audio(lavc_actx, dest, size, src); | |
101 if(n > compressed_frame_size) | |
102 compressed_frame_size = n; //it's valid because lavc encodes in cbr mode | |
103 return n; | |
104 } | |
105 | |
106 | |
107 static int close_lavc(audio_encoder_t *encoder) | |
108 { | |
109 compressed_frame_size = 0; | |
110 return 1; | |
111 } | |
112 | |
113 static int get_frame_size(audio_encoder_t *encoder) | |
114 { | |
115 return compressed_frame_size; | |
116 } | |
117 | |
15244
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
118 static uint32_t lavc_find_atag(char *codec) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
119 { |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
120 if(codec == NULL) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
121 return 0; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
122 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
123 if(! strcasecmp(codec, "mp2")) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
124 return 0x50; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
125 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
126 if(! strcasecmp(codec, "mp3")) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
127 return 0x55; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
128 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
129 if(! strcasecmp(codec, "ac3")) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
130 return 0x2000; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
131 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
132 if(! strcasecmp(codec, "adpcm_ima_wav")) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
133 return 0x11; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
134 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
135 if(! strncasecmp(codec, "bonk", 4)) |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
136 return 0x2048; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
137 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
138 return 0; |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
139 } |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
140 |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
141 |
15234 | 142 int mpae_init_lavc(audio_encoder_t *encoder) |
143 { | |
144 encoder->params.samples_per_frame = encoder->params.sample_rate; | |
145 encoder->params.bitrate = encoder->params.sample_rate * encoder->params.channels * 2 * 8; | |
146 | |
147 if(!lavc_param_acodec) | |
148 { | |
149 mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_NoLavcAudioCodecName); | |
150 return 0; | |
151 } | |
152 | |
153 if(!avcodec_inited){ | |
154 avcodec_init(); | |
155 avcodec_register_all(); | |
156 avcodec_inited=1; | |
157 } | |
158 | |
159 lavc_acodec = avcodec_find_encoder_by_name(lavc_param_acodec); | |
160 if (!lavc_acodec) | |
161 { | |
162 mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_LavcAudioCodecNotFound, lavc_param_acodec); | |
163 return 0; | |
164 } | |
165 if(lavc_param_atag == 0) | |
166 { | |
15244
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
167 #ifdef USE_LIBAVFORMAT |
15234 | 168 lavc_param_atag = codec_get_wav_tag(lavc_acodec->id); |
15244
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
169 #else |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
170 lavc_param_atag = lavc_find_atag(lavc_param_acodec); |
a8a8a4d69a1c
restore old lavc_find_atag to be used when compiling mplayer without libavformat
nicodvb
parents:
15240
diff
changeset
|
171 #endif |
15234 | 172 if(!lavc_param_atag) |
173 { | |
174 mp_msg(MSGT_MENCODER, MSGL_FATAL, "Couldn't find wav tag for specified codec, exit\n"); | |
175 return 0; | |
176 } | |
177 } | |
178 | |
179 lavc_actx = avcodec_alloc_context(); | |
180 if(lavc_actx == NULL) | |
181 { | |
182 mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_CouldntAllocateLavcContext); | |
183 return 0; | |
184 } | |
185 | |
186 // put sample parameters | |
187 lavc_actx->channels = encoder->params.channels; | |
188 lavc_actx->sample_rate = encoder->params.sample_rate; | |
189 lavc_actx->bit_rate = encoder->params.bitrate = lavc_param_abitrate * 1000; | |
190 | |
191 | |
192 /* | |
193 * Special case for adpcm_ima_wav. | |
194 * The bitrate is only dependant on samplerate. | |
195 * We have to known frame_size and block_align in advance, | |
196 * so I just copied the code from libavcodec/adpcm.c | |
197 * | |
198 * However, ms adpcm_ima_wav uses a block_align of 2048, | |
199 * lavc defaults to 1024 | |
200 */ | |
201 if(lavc_param_atag == 0x11) { | |
202 int blkalign = 2048; | |
203 int framesize = (blkalign - 4 * lavc_actx->channels) * 8 / (4 * lavc_actx->channels) + 1; | |
204 lavc_actx->bit_rate = lavc_actx->sample_rate*8*blkalign/framesize; | |
205 } | |
206 | |
207 if(avcodec_open(lavc_actx, lavc_acodec) < 0) | |
208 { | |
209 mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_CouldntOpenCodec, lavc_param_acodec, lavc_param_abitrate); | |
210 return 0; | |
211 } | |
212 | |
213 if(lavc_param_atag == 0x11) { | |
214 lavc_actx->block_align = 2048; | |
215 lavc_actx->frame_size = (lavc_actx->block_align - 4 * lavc_actx->channels) * 8 / (4 * lavc_actx->channels) + 1; | |
216 } | |
217 | |
218 encoder->decode_buffer_size = lavc_actx->frame_size * 2 * encoder->params.channels; | |
219 encoder->bind = bind_lavc; | |
220 encoder->get_frame_size = get_frame_size; | |
221 encoder->encode = encode_lavc; | |
222 encoder->close = close_lavc; | |
223 | |
224 return 1; | |
225 } | |
226 |