6ed0fcd55f76c198d95974f3257cf4231cad9d90
[picodrive.git] / platform / common / mp3_libavcodec.c
1 /*
2  * Some mp3 related code for Sega/Mega CD.
3  * Uses Libav/FFmpeg libavcodec
4  * (C) notaz, 2013
5  *
6  * This work is licensed under the terms of MAME license.
7  * See COPYING file in the top-level directory.
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <libavcodec/avcodec.h>
13 #include <dlfcn.h>
14
15 #include <pico/pico_int.h>
16 #include "mp3.h"
17
18 #if LIBAVCODEC_VERSION_MAJOR < 55
19 #define AVCodecID CodecID
20 #define AV_CODEC_ID_MP3 CODEC_ID_MP3
21 #define AV_CH_LAYOUT_STEREO CH_LAYOUT_STEREO
22 #define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
23 #define request_sample_fmt sample_fmt
24 #endif
25
26 static void *libavcodec;
27 static AVCodecContext *ctx;
28
29 /* avoid compile time linking to libavcodec due to huge list of it's deps..
30  * we also use this old API as newer one is not available on pandora */
31 void (*p_av_init_packet)(AVPacket *pkt);
32 int (*p_avcodec_decode_audio3)(AVCodecContext *avctx, int16_t *samples,
33         int *frame_size_ptr, AVPacket *avpkt);
34
35 int mp3dec_decode(FILE *f, int *file_pos, int file_len)
36 {
37         unsigned char input_buf[2 * 1024];
38         int frame_size;
39         AVPacket avpkt;
40         int bytes_in;
41         int bytes_out;
42         int offset;
43         int len = -1;
44         int retry = 3;
45
46         p_av_init_packet(&avpkt);
47
48         do
49         {
50                 if (*file_pos >= file_len)
51                         return 1; // EOF, nothing to do
52
53                 fseek(f, *file_pos, SEEK_SET);
54                 bytes_in = fread(input_buf, 1, sizeof(input_buf), f);
55
56                 offset = mp3_find_sync_word(input_buf, bytes_in);
57                 if (offset < 0) {
58                         lprintf("find_sync_word (%i/%i) err %i\n",
59                                 *file_pos, file_len, offset);
60                         *file_pos = file_len;
61                         return 1; // EOF
62                 }
63                 *file_pos += offset;
64
65                 // to avoid being flooded with "incorrect frame size" errors,
66                 // we must calculate and pass exact frame size - lame
67                 frame_size = mpeg1_l3_bitrates[input_buf[offset + 2] >> 4];
68                 frame_size = frame_size * 144000 / 44100;
69                 frame_size += (input_buf[offset + 2] >> 1) & 1;
70
71                 if (offset > 0 && bytes_in - offset < frame_size) {
72                         // underflow
73                         continue;
74                 }
75
76                 avpkt.data = input_buf + offset;
77                 avpkt.size = frame_size;
78                 bytes_out = sizeof(cdda_out_buffer);
79 #if LIBAVCODEC_VERSION_MAJOR < 53
80                 // stupidity in v52: enforces this size even when
81                 // it doesn't need/use that much at all
82                 bytes_out = AVCODEC_MAX_AUDIO_FRAME_SIZE;
83 #endif
84
85                 len = p_avcodec_decode_audio3(ctx, cdda_out_buffer,
86                         &bytes_out, &avpkt);
87                 if (len <= 0) {
88                         lprintf("mp3 decode err (%i/%i) %i\n",
89                                 *file_pos, file_len, len);
90
91                         // attempt to skip the offending frame..
92                         *file_pos += 1;
93                 } else
94                         *file_pos += len;
95         }
96         while (len <= 0 && --retry > 0);
97
98         return len <= 0;
99 }
100
101 int mp3dec_start(FILE *f, int fpos_start)
102 {
103         void (*avcodec_register_all)(void);
104         AVCodec *(*avcodec_find_decoder)(enum AVCodecID id);
105 #if LIBAVCODEC_VERSION_MAJOR < 54
106         AVCodecContext *(*avcodec_alloc_context)(void);
107         int (*avcodec_open)(AVCodecContext *avctx, AVCodec *codec);
108 #else
109         AVCodecContext *(*avcodec_alloc_context)(AVCodec *);
110         int (*avcodec_open)(AVCodecContext *avctx, AVCodec *codec, AVDictionary **);
111 #endif
112         void (*av_free)(void *ptr);
113         AVCodec *codec;
114         int ret;
115
116         if (ctx != NULL)
117                 return 0;
118
119 #if LIBAVCODEC_VERSION_MAJOR < 54
120         // either v52 or v53 should be ok
121         if (libavcodec == NULL)
122                 libavcodec = dlopen("libavcodec.so.52", RTLD_NOW);
123         if (libavcodec == NULL)
124                 libavcodec = dlopen("libavcodec.so.53", RTLD_NOW);
125 #else
126         if (libavcodec == NULL)
127                 libavcodec = dlopen("libavcodec.so", RTLD_NOW);
128 #endif
129         if (libavcodec == NULL) {
130                 lprintf("mp3dec: load libavcodec.so: %s\n", dlerror());
131                 return -1;
132         }
133
134         avcodec_register_all = dlsym(libavcodec, "avcodec_register_all");
135         avcodec_find_decoder = dlsym(libavcodec, "avcodec_find_decoder");
136 #if LIBAVCODEC_VERSION_MAJOR < 54
137         avcodec_alloc_context = dlsym(libavcodec, "avcodec_alloc_context");
138         avcodec_open = dlsym(libavcodec, "avcodec_open");
139 #else
140         avcodec_alloc_context = dlsym(libavcodec, "avcodec_alloc_context3");
141         avcodec_open = dlsym(libavcodec, "avcodec_open2");
142 #endif
143         av_free = dlsym(libavcodec, "av_free");
144         p_av_init_packet = dlsym(libavcodec, "av_init_packet");
145         p_avcodec_decode_audio3 = dlsym(libavcodec, "avcodec_decode_audio3");
146
147         if (avcodec_register_all == NULL || avcodec_find_decoder == NULL
148             || avcodec_alloc_context == NULL || avcodec_open == NULL
149             || av_free == NULL
150             || p_av_init_packet == NULL || p_avcodec_decode_audio3 == NULL)
151         {
152                 lprintf("mp3dec: missing symbol(s) in libavcodec.so\n");
153                 return -1;
154         }
155
156         // init decoder
157
158         //avcodec_init();
159         avcodec_register_all();
160
161         codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
162         if (codec == NULL) {
163                 lprintf("mp3dec: codec missing\n");
164                 return -1;
165         }
166
167 #if LIBAVCODEC_VERSION_MAJOR < 54
168         ctx = avcodec_alloc_context();
169         if (ctx == NULL) {
170                 lprintf("mp3dec: avcodec_alloc_context failed\n");
171                 return -1;
172         }
173 #else
174         ctx = avcodec_alloc_context(codec);
175         if (ctx == NULL) {
176                 lprintf("mp3dec: avcodec_alloc_context failed\n");
177                 return -1;
178         }
179 #endif
180         ctx->request_channel_layout = AV_CH_LAYOUT_STEREO;
181         ctx->request_sample_fmt = AV_SAMPLE_FMT_S16;
182         ctx->sample_rate = 44100;
183
184 #if LIBAVCODEC_VERSION_MAJOR < 54
185         ret = avcodec_open(ctx, codec);
186         if (ret < 0) {
187                 lprintf("mp3dec: avcodec_open failed: %d\n", ret);
188                 av_free(ctx);
189                 ctx = NULL;
190                 return -1;
191         }
192 #else
193         ret = avcodec_open(ctx, codec, NULL);
194         if (ret < 0) {
195                 lprintf("mp3dec: avcodec_open failed: %d\n", ret);
196                 av_free(ctx);
197                 ctx = NULL;
198                 return -1;
199         }
200 #endif
201         return 0;
202 }