2 * Copyright 2007 Kevin Ko <kevin.s.ko@gmail.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #ifdef HAVE_FFMPEG_AVCODEC_H
23 #include <ffmpeg/avcodec.h>
24 #include <ffmpeg/avformat.h>
25 #include <ffmpeg/avio.h>
27 #include <libavcodec/avcodec.h>
28 #include <libavformat/avformat.h>
29 #include <libavformat/avio.h>
37 #define NUM_FFMPEG_KEYS 8
42 uint8_t *curr_pkt_buf
;
45 struct ffmpeg_output
{
47 uint8_t *buffer_pos
; /* current buffer position */
51 struct ffmpeg_private
{
52 AVCodecContext
*codec_context
;
53 AVFormatContext
*input_context
;
56 struct ffmpeg_input
*input
;
57 struct ffmpeg_output
*output
;
60 static struct ffmpeg_input
*ffmpeg_input_create(void)
62 struct ffmpeg_input
*input
= xnew(struct ffmpeg_input
, 1);
64 if (av_new_packet(&input
->pkt
, 0) != 0) {
68 input
->curr_pkt_size
= 0;
69 input
->curr_pkt_buf
= input
->pkt
.data
;
73 static void ffmpeg_input_free(struct ffmpeg_input
*input
)
75 av_free_packet(&input
->pkt
);
78 static struct ffmpeg_output
*ffmpeg_output_create(void)
80 struct ffmpeg_output
*output
= xnew(struct ffmpeg_output
, 1);
82 output
->buffer
= xnew(uint8_t, AVCODEC_MAX_AUDIO_FRAME_SIZE
);
83 output
->buffer_pos
= output
->buffer
;
84 output
->buffer_used_len
= 0;
88 static void ffmpeg_output_free(struct ffmpeg_output
*output
)
91 output
->buffer
= NULL
;
95 static inline void ffmpeg_buffer_flush(struct ffmpeg_output
*output
)
97 output
->buffer_pos
= output
->buffer
;
98 output
->buffer_used_len
= 0;
101 static void ffmpeg_init(void)
103 static int inited
= 0;
109 av_log_set_level(AV_LOG_QUIET
);
111 #if (LIBAVFORMAT_VERSION_INT <= ((50<<16) + (4<<8) + 0))
113 register_avcodec(&wmav1_decoder
);
114 register_avcodec(&wmav2_decoder
);
116 /* libavformat versions <= 50.4.0 have asf_init(). From SVN revision
117 * 5697->5707 of asf.c, this function was removed, preferring the use of
118 * explicit calls. Note that version 50.5.0 coincides with SVN revision
119 * 5729, so there is a window of incompatibility for revisions 5707 and 5720
124 /* Uncomment this for shorten (.shn) support.
125 register_avcodec(&shorten_decoder);
129 register_protocol(&file_protocol
);
131 /* We could register decoders explicitly to save memory, but we have to
132 * be careful about compatibility. */
137 static int ffmpeg_open(struct input_plugin_data
*ip_data
)
139 struct ffmpeg_private
*priv
;
142 int stream_index
= -1;
144 AVCodecContext
*cc
= NULL
;
150 err
= av_open_input_file(&ic
, ip_data
->filename
, NULL
, 0, NULL
);
152 d_print("av_open failed: %d\n", err
);
153 err
= -IP_ERROR_FILE_FORMAT
;
157 err
= av_find_stream_info(ic
);
159 d_print("unable to find stream info: %d\n", err
);
160 err
= -IP_ERROR_FILE_FORMAT
;
164 for (i
= 0; i
< ic
->nb_streams
; i
++) {
165 cc
= ic
->streams
[i
]->codec
;
166 if (cc
->codec_type
== CODEC_TYPE_AUDIO
) {
172 if (stream_index
== -1) {
173 d_print("could not find audio stream\n");
174 err
= -IP_ERROR_FILE_FORMAT
;
178 codec
= avcodec_find_decoder(cc
->codec_id
);
180 d_print("codec not found: %d, %s\n", cc
->codec_id
, cc
->codec_name
);
181 err
= -IP_ERROR_FILE_FORMAT
;
185 if (codec
->capabilities
& CODEC_CAP_TRUNCATED
)
186 cc
->flags
|= CODEC_FLAG_TRUNCATED
;
188 if (avcodec_open(cc
, codec
) < 0) {
189 d_print("could not open codec: %d, %s\n", cc
->codec_id
, cc
->codec_name
);
190 err
= -IP_ERROR_FILE_FORMAT
;
193 /* We assume below that no more errors follow. */
197 /* Clean up. cc is never opened at this point. (See above assumption.) */
198 av_close_input_file(ic
);
202 priv
= xnew(struct ffmpeg_private
, 1);
203 priv
->codec_context
= cc
;
204 priv
->input_context
= ic
;
205 priv
->stream_index
= stream_index
;
206 priv
->input
= ffmpeg_input_create();
207 if (priv
->input
== NULL
) {
209 av_close_input_file(ic
);
211 return -IP_ERROR_INTERNAL
;
213 priv
->output
= ffmpeg_output_create();
215 ip_data
->private = priv
;
216 ip_data
->sf
= sf_rate(cc
->sample_rate
) | sf_channels(cc
->channels
) | sf_bits(16) | sf_signed(1);
220 static int ffmpeg_close(struct input_plugin_data
*ip_data
)
222 struct ffmpeg_private
*priv
= ip_data
->private;
224 avcodec_close(priv
->codec_context
);
225 av_close_input_file(priv
->input_context
);
226 ffmpeg_input_free(priv
->input
);
227 ffmpeg_output_free(priv
->output
);
229 ip_data
->private = NULL
;
234 * This returns the number of bytes added to the buffer.
235 * It returns < 0 on error. 0 on EOF.
237 static int ffmpeg_fill_buffer(AVFormatContext
*ic
, AVCodecContext
*cc
, struct ffmpeg_input
*input
,
238 struct ffmpeg_output
*output
)
240 /* frame_size specifies the size of output->buffer for
241 * avcodec_decode_audio2. */
242 int frame_size
= AVCODEC_MAX_AUDIO_FRAME_SIZE
;
246 if (input
->curr_pkt_size
<= 0) {
247 av_free_packet(&input
->pkt
);
248 if (av_read_frame(ic
, &input
->pkt
) < 0) {
249 /* Force EOF once we can read no longer. */
252 input
->curr_pkt_size
= input
->pkt
.size
;
253 input
->curr_pkt_buf
= input
->pkt
.data
;
257 /* The change to avcodec_decode_audio2 occurred between
258 * 51.28.0 and 51.29.0 */
259 #if (LIBAVCODEC_VERSION_INT <= ((51<<16) + (28<<8) + 0))
260 len
= avcodec_decode_audio(cc
, (int16_t *)output
->buffer
, &frame_size
,
261 input
->curr_pkt_buf
, input
->curr_pkt_size
);
263 len
= avcodec_decode_audio2(cc
, (int16_t *) output
->buffer
, &frame_size
,
264 input
->curr_pkt_buf
, input
->curr_pkt_size
);
266 input
->curr_pkt_size
-= len
;
267 input
->curr_pkt_buf
+= len
;
268 if (frame_size
> 0) {
269 output
->buffer_pos
= output
->buffer
;
270 output
->buffer_used_len
= frame_size
;
274 /* This should never get here. */
275 return -IP_ERROR_INTERNAL
;
278 static int ffmpeg_read(struct input_plugin_data
*ip_data
, char *buffer
, int count
)
280 struct ffmpeg_private
*priv
= ip_data
->private;
281 struct ffmpeg_output
*output
= priv
->output
;
285 if (output
->buffer_used_len
== 0) {
286 rc
= ffmpeg_fill_buffer(priv
->input_context
, priv
->codec_context
, priv
->input
, priv
->output
);
291 out_size
= min(output
->buffer_used_len
, count
);
292 memcpy(buffer
, output
->buffer_pos
, out_size
);
293 output
->buffer_used_len
-= out_size
;
294 output
->buffer_pos
+= out_size
;
298 static int ffmpeg_seek(struct input_plugin_data
*ip_data
, double offset
)
300 struct ffmpeg_private
*priv
= ip_data
->private;
301 AVStream
*st
= priv
->input_context
->streams
[priv
->stream_index
];
304 /* There is a bug that was fixed in ffmpeg revision 5099 that affects seeking.
305 * Apparently, the stream's timebase was not used consistently in asf.c.
306 * Prior to 5099, ASF seeking assumed seconds as inputs. There is a
307 * window of incompatibility, since avformat's version was not updated at
308 * the same time. Instead, the transition to 50.3.0 occurred at
310 #if (LIBAVFORMAT_VERSION_INT < ((50<<16)+(3<<8)+0))
311 int64_t pts
= (int64_t) offset
;
313 /* time base is 1/framerate */
314 int64_t pts
= (int64_t) offset
* st
->time_base
.den
;
317 ret
= av_seek_frame(priv
->input_context
, priv
->stream_index
, pts
, 0);
320 return -IP_ERROR_FUNCTION_NOT_SUPPORTED
;
322 ffmpeg_buffer_flush(priv
->output
);
328 static int set_comment(struct keyval
*comment
, int i
, const char *key
, const char *val
)
333 comment
[i
].key
= xstrdup(key
);
334 comment
[i
].val
= xstrdup(val
);
338 static int ffmpeg_read_comments(struct input_plugin_data
*ip_data
, struct keyval
**comments
)
341 struct ffmpeg_private
*priv
= ip_data
->private;
342 AVFormatContext
*ic
= priv
->input_context
;
345 *comments
= xnew0(struct keyval
, NUM_FFMPEG_KEYS
+ 1);
347 i
= set_comment(*comments
, i
, "artist", ic
->author
);
348 i
= set_comment(*comments
, i
, "album", ic
->album
);
349 i
= set_comment(*comments
, i
, "title", ic
->title
);
350 i
= set_comment(*comments
, i
, "genre", ic
->genre
);
353 snprintf(buff
, sizeof(buff
), "%d", ic
->year
);
354 i
= set_comment(*comments
, i
, "date", buff
);
357 if (ic
->track
!= 0) {
358 snprintf(buff
, sizeof(buff
), "%d", ic
->track
);
359 i
= set_comment(*comments
, i
, "tracknumber", buff
);
365 static int ffmpeg_duration(struct input_plugin_data
*ip_data
)
367 struct ffmpeg_private
*priv
= ip_data
->private;
368 return priv
->input_context
->duration
/ 1000000L;
371 const struct input_plugin_ops ip_ops
= {
373 .close
= ffmpeg_close
,
376 .read_comments
= ffmpeg_read_comments
,
377 .duration
= ffmpeg_duration
380 const char *const ip_extensions
[] = { "wma", NULL
};
381 const char *const ip_mime_types
[] = { NULL
};