vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / media / plugins / matroska / matroska_codecs.cpp
blob7bf432f2d7fe7900ddfd45fd031c398fd5950b26
1 /*
2 * Copyright (c) 2004, Marcus Overhagen
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
23 * OF THE POSSIBILITY OF SUCH DAMAGE.
25 #include <stdio.h>
26 #include <string.h>
27 #include <MediaFormats.h>
28 #include "matroska_codecs.h"
30 #define TRACE_MATROSKA
31 #ifdef TRACE_MATROSKA
32 #define TRACE printf
33 #else
34 #define TRACE(a...)
35 #endif
37 #define ERROR(a...) fprintf(stderr, a)
39 struct bitmap_info_header
41 uint32 size;
42 uint32 width;
43 uint32 height;
44 uint16 planes;
45 uint16 bit_count;
46 uint32 compression;
47 uint32 image_size;
48 uint32 x_pels_per_meter;
49 uint32 y_pels_per_meter;
50 uint32 clr_used;
51 uint32 clr_important;
52 } _PACKED;
54 #include "ogg/ogg.h"
55 #include <vector>
59 status_t
60 GetAudioFormat(media_format *format, const char *codec, void *private_data, int private_size)
62 TRACE("private_data: codec '%s', private data size %d\n", codec, private_size);
64 BMediaFormats formats;
65 media_format_description description;
67 if (IS_CODEC(codec, "A_VORBIS")) {
68 description.family = B_MISC_FORMAT_FAMILY;
69 description.u.misc.file_format = 'OggS';
70 description.u.misc.codec = 'vorb';
71 if (B_OK != formats.GetFormatFor(description, format))
72 format->type = B_MEDIA_ENCODED_AUDIO;
74 uint8_t * data_bytes = (uint8_t*)private_data;
75 int packet_count = data_bytes[0] + 1;
76 if (packet_count != 3) {
77 return B_ERROR;
80 int info_packet_size = data_bytes[1];
81 int comment_packet_size = data_bytes[2];
82 int codebook_packet_size = private_size - info_packet_size - comment_packet_size - 3;
84 static uint8_t * vorbis_bytes = new uint8_t[private_size - 3];
85 memcpy(vorbis_bytes, &(data_bytes[3]), private_size - 3);
87 ogg_packet packet;
88 static std::vector<ogg_packet> header_packets;
90 packet.b_o_s = 1;
91 packet.e_o_s = 0;
92 packet.granulepos = 0;
93 packet.packetno = 0;
94 packet.packet = &(vorbis_bytes[0]);
95 packet.bytes = info_packet_size;
96 header_packets.push_back(packet);
98 packet.b_o_s = 0;
99 packet.e_o_s = 0;
100 packet.granulepos = 0;
101 packet.packetno = 1;
102 packet.packet = &(vorbis_bytes[info_packet_size]);
103 packet.bytes = comment_packet_size;
104 header_packets.push_back(packet);
106 packet.b_o_s = 0;
107 packet.e_o_s = 0;
108 packet.granulepos = 0;
109 packet.packetno = 2;
110 packet.packet = &(vorbis_bytes[info_packet_size+comment_packet_size]);
111 packet.bytes = codebook_packet_size;
112 header_packets.push_back(packet);
114 format->SetMetaData(&header_packets, sizeof(header_packets));
116 return B_OK;
119 if (IS_CODEC(codec, "A_MPEG/L3")) {
120 description.family = B_MPEG_FORMAT_FAMILY;
121 description.u.mpeg.id = B_MPEG_1_AUDIO_LAYER_3;
122 if (formats.GetFormatFor(description, format) != B_OK)
123 format->type = B_MEDIA_ENCODED_AUDIO;
125 return B_OK;
128 if (IS_CODEC(codec, "A_AC3")) {
129 description.family = B_WAV_FORMAT_FAMILY;
130 description.u.wav.codec = 0x2000;
132 if (B_OK != formats.GetFormatFor(description, format))
133 format->type = B_MEDIA_ENCODED_AUDIO;
135 // Set the DecoderConfigSize (Not that haiku seems to use it)
136 if (private_size > 0) {
137 TRACE("AC3 private data found, size is %d\n", private_size);
138 if (format->SetMetaData(private_data, private_size) != B_OK) {
139 ERROR("Failed to set Decoder Config\n");
140 return B_ERROR;
144 return B_OK;
147 // The codec name only has to start with A_AAC to be AAC
148 // The rest is some sort of hint for creating the codec specific data
149 if (IS_CODEC(codec, "A_AAC")) {
150 uint64 misc_codec = 'mp4a';
151 media_format_description description;
152 description.family = B_MISC_FORMAT_FAMILY;
153 description.u.misc.file_format = (uint32)(misc_codec >> 32);
154 description.u.misc.codec = (uint32)misc_codec;
155 if (formats.GetFormatFor(description, format) != B_OK)
156 format->type = B_MEDIA_ENCODED_AUDIO;
158 // Set the DecoderConfigSize (Not that haiku seems to use it)
159 if (private_size > 0) {
160 TRACE("AAC private data found, size is %d\n", private_size);
161 if (format->SetMetaData(private_data, private_size) != B_OK) {
162 ERROR("Failed to set Decoder Config\n");
163 return B_ERROR;
167 return B_OK;
170 return B_ERROR;
174 status_t
175 GetVideoFormat(media_format *format, const char *codec, void *private_data, int private_size)
177 TRACE("private_data: codec '%s', private data size %d\n", codec, private_size);
179 BMediaFormats formats;
180 media_format_description description;
182 if (IS_CODEC(codec, "V_MS/VFW/FOURCC")) {
183 if (private_size < (int)sizeof(bitmap_info_header)) {
184 TRACE("private_size too small!\n");
185 return B_ERROR;
187 const bitmap_info_header *bih = (const bitmap_info_header *)private_data;
189 description.family = B_AVI_FORMAT_FAMILY;
190 description.u.avi.codec = bih->compression;
191 if (B_OK != formats.GetFormatFor(description, format))
192 format->type = B_MEDIA_ENCODED_VIDEO;
194 format->user_data_type = B_CODEC_TYPE_INFO;
195 *(uint32 *)format->user_data = bih->compression; format->user_data[4] = 0;
197 return B_OK;
199 if (IS_CODEC(codec, "V_MPEG4/ISO/AVC")) {
200 uint64 codecid = 'avc1';
202 description.family = B_QUICKTIME_FORMAT_FAMILY;
203 description.u.quicktime.codec = codecid;
204 if (B_OK != formats.GetFormatFor(description, format))
205 format->type = B_MEDIA_ENCODED_VIDEO;
207 format->user_data_type = B_CODEC_TYPE_INFO;
208 *(uint32 *)format->user_data = codecid; format->user_data[4] = 0;
210 // Set the DecoderConfigSize (Not that haiku seems to use it)
211 if (private_size > 0) {
212 TRACE("AVC private data found, size is %d\n", private_size);
213 if (format->SetMetaData(private_data, private_size) != B_OK) {
214 ERROR("Failed to set Decoder Config\n");
215 return B_ERROR;
219 return B_OK;
221 TRACE("not a codec!\n");
223 return B_ERROR;