summaryrefslogtreecommitdiff
blob: 21ed6492a44d80859ded0fefe14cc70b0ee1c896 (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
commit 8831bc77d705c03b3f8081de0520dd10afa85c69
Author: Uli Franke <cls@nebadje.org>
Date:   Tue Jan 17 23:23:46 2012 +0100

    BUG(2509): Avoid unaligned reads in avcodec xform.

diff --git a/src/plugins/avcodec/avcodec.c b/src/plugins/avcodec/avcodec.c
index fe58fc5..1b4a659 100644
--- a/src/plugins/avcodec/avcodec.c
+++ b/src/plugins/avcodec/avcodec.c
@@ -36,6 +36,9 @@ typedef struct {
 	guint buffer_size;
 	gboolean no_demuxer;
 
+	gchar *read_out_buffer;
+	gint read_out_buffer_size;
+
 	guint channels;
 	guint samplerate;
 	xmms_sample_format_t sampleformat;
@@ -107,6 +110,7 @@ xmms_avcodec_destroy (xmms_xform_t *xform)
 
 	avcodec_close (data->codecctx);
 	av_free (data->codecctx);
+	av_free (data->read_out_buffer);
 
 	g_string_free (data->outbuf, TRUE);
 	g_free (data->buffer);
@@ -132,6 +136,9 @@ xmms_avcodec_init (xmms_xform_t *xform)
 	data->buffer_size = AVCODEC_BUFFER_SIZE;
 	data->codecctx = NULL;
 
+	data->read_out_buffer = av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
+	data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+
 	xmms_xform_private_data_set (xform, data);
 
 	avcodec_init ();
@@ -196,7 +203,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
 		} else {
 			/* A demuxer plugin forgot to give decoder config? */
 			xmms_log_error ("Decoder config data not found!");
-			return FALSE;
+			goto err;
 		}
 	}
 
@@ -220,7 +227,7 @@ xmms_avcodec_init (xmms_xform_t *xform)
 
 		/* some codecs need to have something read before they set
 		 * the samplerate and channels correctly, unfortunately... */
-		if ((ret = xmms_avcodec_read (xform, buf, 42, &error)) > 0) {
+		if ((ret = xmms_avcodec_read (xform, buf, sizeof (buf), &error)) > 0) {
 			g_string_insert_len (data->outbuf, 0, buf, ret);
 		} else {
 			XMMS_DBG ("First read failed, codec is not working...");
@@ -251,6 +258,9 @@ err:
 	if (data->codecctx) {
 		av_free (data->codecctx);
 	}
+	if (data->read_out_buffer) {
+		av_free (data->read_out_buffer);
+	}
 	g_string_free (data->outbuf, TRUE);
 	g_free (data->extradata);
 	g_free (data);
@@ -263,8 +273,7 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
                    xmms_error_t *error)
 {
 	xmms_avcodec_data_t *data;
-	char outbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
-	gint outbufsize, bytes_read = 0;
+	gint bytes_read = 0;
 	guint size;
 
 	data = xmms_xform_private_data_get (xform);
@@ -330,9 +339,9 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
 		packet.data = data->buffer;
 		packet.size = data->buffer_length;
 
-		outbufsize = sizeof (outbuf);
-		bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) outbuf,
-		                                    &outbufsize, &packet);
+		data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+		bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) data->read_out_buffer,
+		                                    &data->read_out_buffer_size, &packet);
 
 		/* The DTS decoder of ffmpeg is buggy and always returns
 		 * the input buffer length, get frame length from header */
@@ -354,8 +363,8 @@ xmms_avcodec_read (xmms_xform_t *xform, xmms_sample_t *buf, gint len,
 
 		data->buffer_length -= bytes_read;
 
-		if (outbufsize > 0) {
-			g_string_append_len (data->outbuf, outbuf, outbufsize);
+		if (data->read_out_buffer_size > 0) {
+			g_string_append_len (data->outbuf, data->read_out_buffer, data->read_out_buffer_size);
 		}
 
 		size = MIN (data->outbuf->len, len);
@@ -371,8 +380,7 @@ static gint64
 xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, xmms_xform_seek_mode_t whence, xmms_error_t *err)
 {
 	xmms_avcodec_data_t *data;
-	char outbuf[AVCODEC_MAX_AUDIO_FRAME_SIZE];
-	gint outbufsize, bytes_read = 0;
+	gint bytes_read = 0;
 	gint64 ret = -1;
 
 	g_return_val_if_fail (xform, -1);
@@ -396,9 +404,9 @@ xmms_avcodec_seek (xmms_xform_t *xform, gint64 samples, xmms_xform_seek_mode_t w
 		packet.data = data->buffer;
 		packet.size = data->buffer_length;
 
-		outbufsize = sizeof (outbuf);
-		bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) outbuf,
-		                                    &outbufsize, &packet);
+		data->read_out_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
+		bytes_read = avcodec_decode_audio3 (data->codecctx, (short *) data->read_out_buffer,
+		                                    &data->read_out_buffer_size, &packet);
 
 		if (bytes_read < 0 || bytes_read > data->buffer_length) {
 			XMMS_DBG ("Error decoding data!");