2 * Common Source Code Project for Qt : movie saver.
3 * (C) 2016 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * History: Oct 02, 2016 : Initial.
8 #include "csp_logger.h"
9 #include "sound_loader.h"
10 #include "../osd_base.h"
12 SOUND_LOADER::SOUND_LOADER(void *prev_sound_loader, CSP_Logger *logger)
15 _dst_size = _dataptr = 0;
16 _data[0] = _data[1] = _data[2] = _data[3] = NULL;
22 prev_loader = prev_sound_loader;
24 #if defined(USE_LIBAV)
29 audio_stream_idx = -1;
34 SOUND_LOADER::~SOUND_LOADER()
36 if(sound_buffer != NULL) free(sound_buffer);
37 for(int i = 0; i < 4; i++) {
38 if(_data[i] != NULL) free(_data);
42 bool SOUND_LOADER::open(int id, QString filename)
46 if(filename.isEmpty()) {
52 /* register all formats and codecs */
55 /* open input file, and allocate format context */
56 if (avformat_open_input(&fmt_ctx, _filename.toLocal8Bit().constData(), NULL, NULL) < 0) {
57 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Could not open source file %s\n", _filename.toLocal8Bit().constData());
61 /* retrieve stream information */
62 if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
63 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Could not find stream information\n");
66 if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) {
67 audio_stream = fmt_ctx->streams[audio_stream_idx];
68 audio_dec_ctx = audio_stream->codec;
69 //sound_rate = audio_stream->codec->sample_rate;
71 swr_context = swr_alloc();
72 if(swr_context == NULL) {
73 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Could not allocate resampler context\n");
76 av_opt_set_int (swr_context, "in_channel_count", audio_stream->codec->channels, 0);
77 av_opt_set_int (swr_context, "in_sample_rate", audio_stream->codec->sample_rate, 0);
78 av_opt_set_sample_fmt(swr_context, "in_sample_fmt", audio_stream->codec->sample_fmt, 0);
79 av_opt_set_int (swr_context, "out_channel_count", 2, 0);
80 av_opt_set_int (swr_context, "out_sample_rate", sound_rate, 0);
81 av_opt_set_sample_fmt(swr_context, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
83 /* initialize the resampling context */
84 if ((ret = swr_init(swr_context)) < 0) {
85 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Failed to initialize the resampling context\n");
89 /* dump input information to stderr */
90 av_dump_format(fmt_ctx, 0, _filename.toLocal8Bit().constData(), 0);
91 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Audio is %d Hz ", sound_rate);
93 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Could not find audio or video stream in the input, aborting\n");
97 frame = av_frame_alloc();
99 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Could not allocate frame\n");
100 ret = AVERROR(ENOMEM);
104 /* initialize packet, set data to NULL, let the demuxer fill it */
105 av_init_packet(&pkt);
108 // ToDo : Initialize SWScaler and SWresampler.
109 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "SOUND_LOADER: Loading movie completed.\n");
116 void SOUND_LOADER::close(void)
118 #if defined(USE_LIBAV)
119 if(audio_dec_ctx != NULL) avcodec_close(audio_dec_ctx);
120 avformat_close_input(&fmt_ctx);
121 swr_free(&swr_context);
124 audio_dec_ctx = NULL;
127 audio_stream_idx = -1;
130 for(int i = 0; i < 4; i++) {
131 if(_data[i] != NULL) free(_data[i]);
134 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "SOUND_LOADER: Close sound.");
137 #if defined(USE_LIBAV)
138 int SOUND_LOADER::decode_packet(int *got_frame, int cached)
141 int decoded = pkt.size;
143 if (pkt.stream_index == audio_stream_idx) {
144 ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt);
146 char str_buf[AV_ERROR_MAX_STRING_SIZE] = {0};
147 av_make_error_string(str_buf, AV_ERROR_MAX_STRING_SIZE, ret);
148 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Error decoding audio frame (%s)\n", str_buf);
151 /* Some audio decoders decode only part of the packet, and have to be
152 * called again with the remainder of the packet data.
153 * Sample: fate-suite/lossless-audio/luckynight-partial.shn
154 * Also, some decoders might over-read the packet. */
155 decoded = FFMIN(ret, pkt.size);
158 //size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample((enum AVSampleFormat)frame->format);
159 //char str_buf[AV_TS_MAX_STRING_SIZE] = {0};
160 AVCodecContext *c = audio_stream->codec;
161 int dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_context, c->sample_rate) + frame->nb_samples,
162 c->sample_rate, c->sample_rate, AV_ROUND_UP);
163 //av_ts_make_time_string(str_buf, frame->pts, &audio_dec_ctx->time_base);
164 //p_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_SOUND_LOADER,"audio_frame%s n:%d nb_samples:%d pts:%s\n",
165 // cached ? "(cached)" : "",
166 // audio_frame_count++, frame->nb_samples,
168 /* Write the raw audio data samples of the first plane. This works
169 * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However,
170 * most audio decoders output planar audio, which uses a separate
171 * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P).
172 * In other words, this code will write only the first audio channel
174 * You should use libswresample or libavfilter to convert the frame
176 _data[0] = (uint8_t *)malloc((long)dst_nb_samples * 2 * sizeof(int16_t));
177 _data[1] = _data[2] = _data[3] = NULL;
178 if(_data[0] == NULL) {
179 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Error allocating local buffers\n");
183 ret = swr_convert(swr_context,
184 _data, dst_nb_samples,
185 (const uint8_t **)frame->data, frame->nb_samples);
187 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Error while converting\n");
190 _dst_size += dst_nb_samples;
191 if(_data_size <= (uint)(_dst_size * 2 * sizeof(int16_t))) {
192 sound_buffer = (int16_t *)realloc(sound_buffer, _data_size << 1);
193 if(sound_buffer == NULL) {
194 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Error re-allocate sound buffer");
195 if(_data[0] != NULL) free(_data[0]);
201 my_memcpy(&sound_buffer[_dataptr], _data[0], (long)dst_nb_samples * 2 * sizeof(int16_t));
202 _dataptr += (dst_nb_samples * 2);
210 /* If we use frame reference counting, we own the data and need
211 * to de-reference it when we don't use it anymore */
213 av_frame_unref(frame);
217 int SOUND_LOADER::open_codec_context(int *stream_idx,
218 AVFormatContext *fmt_ctx, enum AVMediaType type)
220 int ret, stream_index;
222 AVCodecContext *dec_ctx = NULL;
224 AVDictionary *opts = NULL;
226 ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
228 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Could not find %s stream in input file '%s'\n",
229 av_get_media_type_string(type), _filename.toLocal8Bit().constData());
233 st = fmt_ctx->streams[stream_index];
235 /* find decoder for the stream */
237 dec = avcodec_find_decoder(dec_ctx->codec_id);
239 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Failed to find %s codec\n",
240 av_get_media_type_string(type));
241 return AVERROR(EINVAL);
244 /* Init the decoders, with or without reference counting */
245 av_dict_set(&opts, "refcounted_frames", "1", 0);
246 if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) {
247 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER, "Failed to open %s codec\n",
248 av_get_media_type_string(type));
251 *stream_idx = stream_index;
257 int SOUND_LOADER::get_format_from_sample_fmt(const char **fmt,
258 enum AVSampleFormat sample_fmt)
261 struct sample_fmt_entry {
262 enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le;
263 } sample_fmt_entries[] = {
264 { AV_SAMPLE_FMT_U8, "u8", "u8" },
265 { AV_SAMPLE_FMT_S16, "s16be", "s16le" },
266 { AV_SAMPLE_FMT_S32, "s32be", "s32le" },
267 { AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
268 { AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
272 for (i = 0; i < (int)FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
273 struct sample_fmt_entry *entry = &sample_fmt_entries[i];
274 if (sample_fmt == entry->sample_fmt) {
275 *fmt = AV_NE(entry->fmt_be, entry->fmt_le);
280 p_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SOUND_LOADER,
281 "sample format %s is not supported as output format\n",
282 av_get_sample_fmt_name(sample_fmt));
287 int SOUND_LOADER::do_decode_frames(void)
292 if(sound_buffer != NULL) {
296 #if defined(USE_LIBAV)
297 _data_size = 65536 * 2 * sizeof(int16_t);
298 sound_buffer = (int16_t *)malloc(_data_size);
299 if(sound_buffer == NULL) {
305 ret = av_read_frame(fmt_ctx, &pkt);
307 decoded = decode_packet(&got_frame, 0);
308 } while((ret == 0) && (decoded >= 0));
315 const int16_t* SOUND_LOADER::get_sound_buffer(void)
317 return (const int16_t *)sound_buffer;
320 const int SOUND_LOADER::get_id(void)
325 void SOUND_LOADER::set_id(int id)
330 const void *SOUND_LOADER::get_prev_sound_loader(void)
332 return (const void *)prev_loader;
335 const int SOUND_LOADER::get_dst_size(void)
337 return (const int)_dst_size;
340 void SOUND_LOADER::free_sound_buffer(int16_t *p)
343 if(sound_buffer != NULL) free(sound_buffer);
351 if(p == sound_buffer) {
361 void SOUND_LOADER::set_sound_rate(int rate)