summaryrefslogtreecommitdiff
path: root/decoders/ffmpeg_decoder.cpp
blob: 7a347243f77a6ccdf284504e272ed5400f6785bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "ffmpeg_decoder.h"

#include <iostream>
#include <cstring>

DecoderFFmpeg::DecoderFFmpeg(const std::string& filename) {
	av_register_all();
	
	lavf_ctx = NULL;
	std::cerr << "Opening file: " << avformat_open_input(&lavf_ctx, filename.c_str(), 0, 0) << std::endl;
	
	av_find_stream_info(lavf_ctx);
	
	av_dump_format(lavf_ctx, 0, filename.c_str(), 0);
	
	lavc_ctx = lavf_ctx->streams[0]->codec;
	samplerate = lavc_ctx->sample_rate;
	channels = lavc_ctx->channels;
	codec = avcodec_find_decoder(lavc_ctx->codec_id);
	
	std::cerr << "Opening decoder: " << avcodec_open(lavc_ctx, codec) << std::endl;

	temp_buffer = NULL;
}

DecoderFFmpeg::~DecoderFFmpeg() {
	avcodec_close(lavc_ctx);
	av_close_input_file(lavf_ctx);
}

std::size_t DecoderFFmpeg::read(char* buf, std::size_t buf_size) {
	if(temp_buffer) {
		std::size_t buffer_size = std::min(temp_buffer_size - temp_buffer_pos, buf_size);
		std::memcpy(buf, temp_buffer + temp_buffer_pos, buffer_size);
		temp_buffer_pos += buffer_size;
		if(temp_buffer_pos == temp_buffer_size) {
			delete[] temp_buffer;
			temp_buffer = NULL;
		}
		return buffer_size;
	}

	AVPacket packet;

	if(av_read_frame(lavf_ctx, &packet) < 0)
		return -1;

	char local_buf[AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
	std::size_t local_buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
	
	int len = avcodec_decode_audio3(lavc_ctx, (int16_t*)local_buf, (int*)&local_buf_size, &packet);

	av_free_packet(&packet);

	if(len < 0)
		return -1;

	if(local_buf_size > buf_size) {
		std::memcpy(buf, local_buf, buf_size);
		temp_buffer_size = local_buf_size - buf_size;
		temp_buffer = new char[temp_buffer_size];
		temp_buffer_pos = 0;
		memcpy(temp_buffer, local_buf + buf_size, temp_buffer_size);
		return buf_size;
	} else {
		std::memcpy(buf, local_buf, local_buf_size);
		return local_buf_size;
	}
}