1 /* 2 * Copyright 2004, 2006, Jérôme Duval. 3 * Copyright 2003-2004, Andrew Bachmann. 4 * Copyright 2002-2004, 2006 Marcus Overhagen. 5 * Copyright 2002, Eric Jaessler. 6 * All rights reserved. Distributed under the terms of the MIT license. 7 */ 8 9 10 #include <inttypes.h> 11 #include <stdio.h> 12 #include <string.h> 13 14 #include <MediaDefs.h> 15 #include <MediaNode.h> 16 #include <Roster.h> 17 18 #include "debug.h" 19 20 #include "DataExchange.h" 21 #include "MediaMisc.h" 22 23 24 #define META_DATA_MAX_SIZE (16 << 20) 25 #define META_DATA_AREA_MIN_SIZE 32000 26 27 28 // #pragma mark - media_destination 29 30 31 media_destination::media_destination(port_id port, int32 id) 32 : 33 port(port), 34 id(id) 35 { 36 } 37 38 39 media_destination::media_destination(const media_destination& clone) 40 : 41 port(clone.port), 42 id(clone.id) 43 { 44 } 45 46 47 media_destination& 48 media_destination::operator=(const media_destination& clone) 49 { 50 port = clone.port; 51 id = clone.id; 52 return *this; 53 } 54 55 56 media_destination::media_destination() 57 : 58 port(-1), 59 id(-1) 60 { 61 } 62 63 64 media_destination::~media_destination() 65 { 66 } 67 68 69 media_destination media_destination::null(-1, -1); 70 71 72 // #pragma mark - media_source 73 74 75 media_source::media_source(port_id port, 76 int32 id) 77 : 78 port(port), 79 id(id) 80 { 81 } 82 83 84 media_source::media_source(const media_source& clone) 85 : 86 port(clone.port), 87 id(clone.id) 88 { 89 } 90 91 92 media_source& 93 media_source::operator=(const media_source& clone) 94 { 95 port = clone.port; 96 id = clone.id; 97 return *this; 98 } 99 100 101 media_source::media_source() 102 : 103 port(-1), 104 id(-1) 105 { 106 } 107 108 109 media_source::~media_source() 110 { 111 } 112 113 114 media_source media_source::null(-1, -1); 115 116 117 // #pragma mark - 118 119 120 bool 121 operator==(const media_destination& a, const media_destination& b) 122 { 123 return a.port == b.port && a.id == b.id; 124 } 125 126 127 bool 128 operator!=(const media_destination& a, const media_destination& b) 129 { 130 return a.port != b.port || a.id != b.id; 131 } 132 133 134 bool 135 operator<(const media_destination& a, const media_destination& b) 136 { 137 UNIMPLEMENTED(); 138 return false; 139 } 140 141 142 bool 143 operator==(const media_source& a, const media_source& b) 144 { 145 return a.port == b.port && a.id == b.id; 146 } 147 148 149 bool 150 operator!=(const media_source& a, const media_source& b) 151 { 152 return a.port != b.port || a.id != b.id; 153 } 154 155 156 bool 157 operator<(const media_source& a, const media_source& b) 158 { 159 UNIMPLEMENTED(); 160 return false; 161 } 162 163 164 bool 165 operator==(const media_node& a, const media_node& b) 166 { 167 return a.node == b.node && a.port == b.port && a.kind == b.kind; 168 } 169 170 171 bool 172 operator!=(const media_node& a, const media_node& b) 173 { 174 return a.node != b.node || a.port != b.port || a.kind != b.kind; 175 } 176 177 178 bool 179 operator<(const media_node& a, const media_node& b) 180 { 181 UNIMPLEMENTED(); 182 return false; 183 } 184 185 186 // #pragma mark - 187 188 189 media_multi_audio_format media_raw_audio_format::wildcard; 190 191 media_multi_audio_format media_multi_audio_format::wildcard; 192 193 media_encoded_audio_format media_encoded_audio_format::wildcard = {{0}}; 194 195 media_video_display_info media_video_display_info::wildcard = {(color_space)0}; 196 197 media_raw_video_format media_raw_video_format::wildcard = {0}; 198 199 media_encoded_video_format media_encoded_video_format::wildcard = {{0}}; 200 201 media_multistream_format media_multistream_format::wildcard = {0}; 202 203 204 // #pragma mark - media_format::Matches() support 205 206 207 static bool 208 raw_audio_format_matches(const media_raw_audio_format& a, 209 const media_raw_audio_format& b) 210 { 211 if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate) 212 return false; 213 if (a.channel_count != 0 && b.channel_count != 0 214 && a.channel_count != b.channel_count) { 215 return false; 216 } 217 if (a.format != 0 && b.format != 0 && a.format != b.format) 218 return false; 219 if (a.byte_order != 0 && b.byte_order != 0 && a.byte_order != b.byte_order) 220 return false; 221 if (a.buffer_size != 0 && b.buffer_size != 0 222 && a.buffer_size != b.buffer_size) { 223 return false; 224 } 225 if (a.frame_rate != 0 && b.frame_rate != 0 && a.frame_rate != b.frame_rate) 226 return false; 227 return true; 228 } 229 230 231 static bool 232 multi_audio_info_matches(const media_multi_audio_info& a, 233 const media_multi_audio_info& b) 234 { 235 if (a.channel_mask != 0 && b.channel_mask != 0 236 && a.channel_mask != b.channel_mask) { 237 return false; 238 } 239 if (a.valid_bits != 0 && b.valid_bits != 0 && a.valid_bits != b.valid_bits) 240 return false; 241 if (a.matrix_mask != 0 && b.matrix_mask != 0 242 && a.matrix_mask != b.matrix_mask) { 243 return false; 244 } 245 return true; 246 } 247 248 249 static bool 250 multi_audio_format_matches(const media_multi_audio_format& a, 251 const media_multi_audio_format& b) 252 { 253 return raw_audio_format_matches(a, b) && multi_audio_info_matches(a, b); 254 } 255 256 257 static bool 258 raw_video_format_matches(const media_raw_video_format& a, 259 const media_raw_video_format& b) 260 { 261 if (a.field_rate != 0 && b.field_rate != 0 262 && a.field_rate != b.field_rate) { 263 return false; 264 } 265 if (a.interlace != 0 && b.interlace != 0 266 && a.interlace != b.interlace) { 267 return false; 268 } 269 if (a.first_active != 0 && b.first_active != 0 270 && a.first_active != b.first_active) { 271 return false; 272 } 273 if (a.last_active != 0 && b.last_active != 0 274 && a.last_active != b.last_active) { 275 return false; 276 } 277 if (a.orientation != 0 && b.orientation != 0 278 && a.orientation != b.orientation) { 279 return false; 280 } 281 if (a.pixel_width_aspect != 0 && b.pixel_width_aspect != 0 282 && a.pixel_width_aspect != b.pixel_width_aspect) { 283 return false; 284 } 285 if (a.pixel_height_aspect != 0 && b.pixel_height_aspect != 0 286 && a.pixel_height_aspect != b.pixel_height_aspect) { 287 return false; 288 } 289 if (a.display.format != 0 && b.display.format != 0 290 && a.display.format != b.display.format) { 291 return false; 292 } 293 if (a.display.line_width != 0 && b.display.line_width != 0 294 && a.display.line_width != b.display.line_width) { 295 return false; 296 } 297 if (a.display.line_count != 0 && b.display.line_count != 0 298 && a.display.line_count != b.display.line_count) { 299 return false; 300 } 301 if (a.display.bytes_per_row != 0 && b.display.bytes_per_row != 0 302 && a.display.bytes_per_row != b.display.bytes_per_row) { 303 return false; 304 } 305 if (a.display.pixel_offset != 0 && b.display.pixel_offset != 0 306 && a.display.pixel_offset != b.display.pixel_offset) { 307 return false; 308 } 309 if (a.display.line_offset != 0 && b.display.line_offset != 0 310 && a.display.line_offset != b.display.line_offset) { 311 return false; 312 } 313 if (a.display.flags != 0 && b.display.flags != 0 314 && a.display.flags != b.display.flags) { 315 return false; 316 } 317 318 return true; 319 } 320 321 322 static bool 323 multistream_format_matches(const media_multistream_format& a, 324 const media_multistream_format& b) 325 { 326 if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0 327 && a.avg_bit_rate != b.avg_bit_rate) { 328 return false; 329 } 330 if (a.max_bit_rate != 0 && b.max_bit_rate != 0 331 && a.max_bit_rate != b.max_bit_rate) { 332 return false; 333 } 334 if (a.avg_chunk_size != 0 && b.avg_chunk_size != 0 335 && a.avg_chunk_size != b.avg_chunk_size) { 336 return false; 337 } 338 if (a.max_chunk_size != 0 && b.max_chunk_size != 0 339 && a.max_chunk_size != b.max_chunk_size) { 340 return false; 341 } 342 if (a.flags != 0 && b.flags != 0 && a.flags != b.flags) 343 return false; 344 if (a.format != 0 && b.format != 0 && a.format != b.format) 345 return false; 346 347 if (a.format == 0 && b.format == 0) { 348 // TODO: How do we compare two formats with no type? 349 return true; 350 } 351 352 switch ((a.format != 0) ? a.format : b.format) { 353 default: 354 return true; // TODO: really? 355 356 case media_multistream_format::B_VID: 357 if (a.u.vid.frame_rate != 0 && b.u.vid.frame_rate != 0 358 && a.u.vid.frame_rate != b.u.vid.frame_rate) { 359 return false; 360 } 361 if (a.u.vid.width != 0 && b.u.vid.width != 0 362 && a.u.vid.width != b.u.vid.width) { 363 return false; 364 } 365 if (a.u.vid.height != 0 && b.u.vid.height != 0 366 && a.u.vid.height != b.u.vid.height) { 367 return false; 368 } 369 if (a.u.vid.space != 0 && b.u.vid.space != 0 370 && a.u.vid.space != b.u.vid.space) { 371 return false; 372 } 373 if (a.u.vid.sampling_rate != 0 && b.u.vid.sampling_rate != 0 374 && a.u.vid.sampling_rate != b.u.vid.sampling_rate) { 375 return false; 376 } 377 if (a.u.vid.sample_format != 0 && b.u.vid.sample_format != 0 378 && a.u.vid.sample_format != b.u.vid.sample_format) { 379 return false; 380 } 381 if (a.u.vid.byte_order != 0 && b.u.vid.byte_order != 0 382 && a.u.vid.byte_order != b.u.vid.byte_order) { 383 return false; 384 } 385 if (a.u.vid.channel_count != 0 && b.u.vid.channel_count != 0 386 && a.u.vid.channel_count != b.u.vid.channel_count) { 387 return false; 388 } 389 return true; 390 391 case media_multistream_format::B_AVI: 392 if (a.u.avi.us_per_frame != 0 && b.u.avi.us_per_frame != 0 393 && a.u.avi.us_per_frame != b.u.avi.us_per_frame) { 394 return false; 395 } 396 if (a.u.avi.width != 0 && b.u.avi.width != 0 397 && a.u.avi.width != b.u.avi.width) { 398 return false; 399 } 400 if (a.u.avi.height != 0 && b.u.avi.height != 0 401 && a.u.avi.height != b.u.avi.height) { 402 return false; 403 } 404 if (a.u.avi.type_count != 0 && b.u.avi.type_count != 0 405 && a.u.avi.type_count != b.u.avi.type_count) { 406 return false; 407 } 408 if (a.u.avi.types[0] != 0 && b.u.avi.types[0] != 0 409 && a.u.avi.types[0] != b.u.avi.types[0]) { 410 return false; 411 } 412 if (a.u.avi.types[1] != 0 && b.u.avi.types[1] != 0 413 && a.u.avi.types[1] != b.u.avi.types[1]) { 414 return false; 415 } 416 if (a.u.avi.types[2] != 0 && b.u.avi.types[2] != 0 417 && a.u.avi.types[2] != b.u.avi.types[2]) { 418 return false; 419 } 420 if (a.u.avi.types[3] != 0 && b.u.avi.types[3] != 0 421 && a.u.avi.types[3] != b.u.avi.types[3]) { 422 return false; 423 } 424 if (a.u.avi.types[4] != 0 && b.u.avi.types[4] != 0 425 && a.u.avi.types[4] != b.u.avi.types[4]) { 426 return false; 427 } 428 return true; 429 } 430 } 431 432 433 static bool 434 encoded_audio_format_matches(const media_encoded_audio_format& a, 435 const media_encoded_audio_format& b) 436 { 437 if (!raw_audio_format_matches(a.output, b.output)) 438 return false; 439 if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding) 440 return false; 441 if (a.bit_rate != 0 && b.bit_rate != 0 && a.bit_rate != b.bit_rate) 442 return false; 443 if (a.frame_size != 0 && b.frame_size != 0 && a.frame_size != b.frame_size) 444 return false; 445 if (!multi_audio_info_matches(a.multi_info, b.multi_info)) 446 return false; 447 448 if (a.encoding == 0 && b.encoding == 0) 449 return true; // can't compare 450 451 switch((a.encoding != 0) ? a.encoding : b.encoding) { 452 case media_encoded_audio_format::B_ANY: 453 default: 454 return true; 455 } 456 } 457 458 459 static bool 460 encoded_video_format_matches(const media_encoded_video_format& a, 461 const media_encoded_video_format& b) 462 { 463 if (!raw_video_format_matches(a.output, b.output)) 464 return false; 465 if (a.encoding != 0 && b.encoding != 0 && a.encoding != b.encoding) 466 return false; 467 468 if (a.avg_bit_rate != 0 && b.avg_bit_rate != 0 469 && a.avg_bit_rate != b.avg_bit_rate) { 470 return false; 471 } 472 if (a.max_bit_rate != 0 && b.max_bit_rate != 0 473 && a.max_bit_rate != b.max_bit_rate) { 474 return false; 475 } 476 if (a.frame_size != 0 && b.frame_size != 0 477 && a.frame_size != b.frame_size) { 478 return false; 479 } 480 if (a.forward_history != 0 && b.forward_history != 0 481 && a.forward_history != b.forward_history) { 482 return false; 483 } 484 if (a.backward_history != 0 && b.backward_history != 0 485 && a.backward_history != b.backward_history) { 486 return false; 487 } 488 489 if (a.encoding == 0 && b.encoding == 0) 490 return true; // can't compare 491 492 switch((a.encoding != 0) ? a.encoding : b.encoding) { 493 case media_encoded_video_format::B_ANY: 494 default: 495 return true; 496 } 497 } 498 499 500 // #pragma mark - media_format::SpecializeTo() support 501 502 503 static void 504 raw_audio_format_specialize(media_raw_audio_format* format, 505 const media_raw_audio_format* other) 506 { 507 if (format->frame_rate == 0) 508 format->frame_rate = other->frame_rate; 509 if (format->channel_count == 0) 510 format->channel_count = other->channel_count; 511 if (format->format == 0) 512 format->format = other->format; 513 if (format->byte_order == 0) 514 format->byte_order = other->byte_order; 515 if (format->buffer_size == 0) 516 format->buffer_size = other->buffer_size; 517 if (format->frame_rate == 0) 518 format->frame_rate = other->frame_rate; 519 } 520 521 522 static void 523 multi_audio_info_specialize(media_multi_audio_info* format, 524 const media_multi_audio_info* other) 525 { 526 if (format->channel_mask == 0) 527 format->channel_mask = other->channel_mask; 528 if (format->valid_bits == 0) 529 format->valid_bits = other->valid_bits; 530 if (format->matrix_mask == 0) 531 format->matrix_mask = other->matrix_mask; 532 } 533 534 535 static void 536 multi_audio_format_specialize(media_multi_audio_format* format, 537 const media_multi_audio_format* other) 538 { 539 raw_audio_format_specialize(format, other); 540 multi_audio_info_specialize(format, other); 541 } 542 543 544 static void 545 raw_video_format_specialize(media_raw_video_format* format, 546 const media_raw_video_format* other) 547 { 548 if (format->field_rate == 0) 549 format->field_rate = other->field_rate; 550 if (format->interlace == 0) 551 format->interlace = other->interlace; 552 if (format->first_active == 0) 553 format->first_active = other->first_active; 554 if (format->last_active == 0) 555 format->last_active = other->last_active; 556 if (format->orientation == 0) 557 format->orientation = other->orientation; 558 if (format->pixel_width_aspect == 0) 559 format->pixel_width_aspect = other->pixel_width_aspect; 560 if (format->pixel_height_aspect == 0) 561 format->pixel_height_aspect = other->pixel_height_aspect; 562 if (format->display.format == 0) 563 format->display.format = other->display.format; 564 if (format->display.line_width == 0) 565 format->display.line_width = other->display.line_width; 566 if (format->display.line_count == 0) 567 format->display.line_count = other->display.line_count; 568 if (format->display.bytes_per_row == 0) 569 format->display.bytes_per_row = other->display.bytes_per_row; 570 if (format->display.pixel_offset == 0) 571 format->display.pixel_offset = other->display.pixel_offset; 572 if (format->display.line_offset == 0) 573 format->display.line_offset = other->display.line_offset; 574 if (format->display.flags == 0) 575 format->display.flags = other->display.flags; 576 } 577 578 579 static void 580 multistream_format_specialize(media_multistream_format* format, 581 const media_multistream_format* other) 582 { 583 if (format->avg_bit_rate == 0) 584 format->avg_bit_rate = other->avg_bit_rate; 585 if (format->max_bit_rate == 0) 586 format->max_bit_rate = other->max_bit_rate; 587 if (format->avg_chunk_size == 0) 588 format->avg_chunk_size = other->avg_chunk_size; 589 if (format->max_chunk_size == 0) 590 format->max_chunk_size = other->max_chunk_size; 591 if (format->flags == 0) 592 format->flags = other->flags; 593 if (format->format == 0) 594 format->format = other->format; 595 596 switch (format->format) { 597 case media_multistream_format::B_VID: 598 if (format->u.vid.frame_rate == 0) 599 format->u.vid.frame_rate = other->u.vid.frame_rate; 600 if (format->u.vid.width == 0) 601 format->u.vid.width = other->u.vid.width; 602 if (format->u.vid.height == 0) 603 format->u.vid.height = other->u.vid.height; 604 if (format->u.vid.space == 0) 605 format->u.vid.space = other->u.vid.space; 606 if (format->u.vid.sampling_rate == 0) 607 format->u.vid.sampling_rate = other->u.vid.sampling_rate; 608 if (format->u.vid.sample_format == 0) 609 format->u.vid.sample_format = other->u.vid.sample_format; 610 if (format->u.vid.byte_order == 0) 611 format->u.vid.byte_order = other->u.vid.byte_order; 612 if (format->u.vid.channel_count == 0) 613 format->u.vid.channel_count = other->u.vid.channel_count; 614 break; 615 616 case media_multistream_format::B_AVI: 617 if (format->u.avi.us_per_frame == 0) 618 format->u.avi.us_per_frame = other->u.avi.us_per_frame; 619 if (format->u.avi.width == 0) 620 format->u.avi.width = other->u.avi.width; 621 if (format->u.avi.height == 0) 622 format->u.avi.height = other->u.avi.height; 623 if (format->u.avi.type_count == 0) 624 format->u.avi.type_count = other->u.avi.type_count; 625 if (format->u.avi.types[0] == 0) 626 format->u.avi.types[0] = other->u.avi.types[0]; 627 if (format->u.avi.types[1] == 0) 628 format->u.avi.types[1] = other->u.avi.types[1]; 629 if (format->u.avi.types[2] == 0) 630 format->u.avi.types[2] = other->u.avi.types[2]; 631 if (format->u.avi.types[3] == 0) 632 format->u.avi.types[3] = other->u.avi.types[3]; 633 if (format->u.avi.types[4] == 0) 634 format->u.avi.types[4] = other->u.avi.types[4]; 635 break; 636 637 default: 638 ERROR("media_format::SpecializeTo can't specialize " 639 "media_multistream_format of format %" B_PRId32 "\n", 640 format->format); 641 } 642 } 643 644 645 static void 646 encoded_audio_format_specialize(media_encoded_audio_format* format, 647 const media_encoded_audio_format* other) 648 { 649 raw_audio_format_specialize(&format->output, &other->output); 650 if (format->encoding == 0) 651 format->encoding = other->encoding; 652 if (format->bit_rate == 0) 653 format->bit_rate = other->bit_rate; 654 if (format->frame_size == 0) 655 format->frame_size = other->frame_size; 656 multi_audio_info_specialize(&format->multi_info, &other->multi_info); 657 } 658 659 660 static void 661 encoded_video_format_specialize(media_encoded_video_format* format, 662 const media_encoded_video_format* other) 663 { 664 raw_video_format_specialize(&format->output, &other->output); 665 if (format->avg_bit_rate == 0) 666 format->avg_bit_rate = other->avg_bit_rate; 667 if (format->max_bit_rate == 0) 668 format->max_bit_rate = other->max_bit_rate; 669 if (format->encoding == 0) 670 format->encoding = other->encoding; 671 if (format->frame_size == 0) 672 format->frame_size = other->frame_size; 673 if (format->forward_history == 0) 674 format->forward_history = other->forward_history; 675 if (format->backward_history == 0) 676 format->backward_history = other->backward_history; 677 } 678 679 680 // #pragma mark - media_format 681 682 683 bool 684 media_format::Matches(const media_format* other) const 685 { 686 CALLED(); 687 688 if (type == 0 && other->type == 0) { 689 // TODO: How do we compare two formats with no type? 690 return true; 691 } 692 693 if (type != 0 && other->type != 0 && type != other->type) 694 return false; 695 696 switch ((type != 0) ? type : other->type) { 697 case B_MEDIA_RAW_AUDIO: 698 return multi_audio_format_matches(u.raw_audio, other->u.raw_audio); 699 700 case B_MEDIA_RAW_VIDEO: 701 return raw_video_format_matches(u.raw_video, other->u.raw_video); 702 703 case B_MEDIA_MULTISTREAM: 704 return multistream_format_matches(u.multistream, 705 other->u.multistream); 706 707 case B_MEDIA_ENCODED_AUDIO: 708 return encoded_audio_format_matches(u.encoded_audio, 709 other->u.encoded_audio); 710 711 case B_MEDIA_ENCODED_VIDEO: 712 return encoded_video_format_matches(u.encoded_video, 713 other->u.encoded_video); 714 715 default: 716 return true; // TODO: really? 717 } 718 } 719 720 721 void 722 media_format::SpecializeTo(const media_format* otherFormat) 723 { 724 CALLED(); 725 726 if (type == 0 && otherFormat->type == 0) { 727 ERROR("media_format::SpecializeTo can't specialize wildcard to other " 728 "wildcard format\n"); 729 return; 730 } 731 732 if (type == 0) 733 type = otherFormat->type; 734 735 switch (type) { 736 case B_MEDIA_RAW_AUDIO: 737 multi_audio_format_specialize(&u.raw_audio, 738 &otherFormat->u.raw_audio); 739 return; 740 741 case B_MEDIA_RAW_VIDEO: 742 raw_video_format_specialize(&u.raw_video, 743 &otherFormat->u.raw_video); 744 return; 745 746 case B_MEDIA_MULTISTREAM: 747 multistream_format_specialize(&u.multistream, 748 &otherFormat->u.multistream); 749 return; 750 751 case B_MEDIA_ENCODED_AUDIO: 752 encoded_audio_format_specialize(&u.encoded_audio, 753 &otherFormat->u.encoded_audio); 754 return; 755 756 case B_MEDIA_ENCODED_VIDEO: 757 encoded_video_format_specialize(&u.encoded_video, 758 &otherFormat->u.encoded_video); 759 return; 760 761 default: 762 ERROR("media_format::SpecializeTo can't specialize format " 763 "type %d\n", type); 764 } 765 } 766 767 768 status_t 769 media_format::SetMetaData(const void* data, size_t size) 770 { 771 if (!data || size < 0 || size > META_DATA_MAX_SIZE) 772 return B_BAD_VALUE; 773 774 void* new_addr; 775 area_id new_area; 776 if (size < META_DATA_AREA_MIN_SIZE) { 777 new_area = B_BAD_VALUE; 778 new_addr = malloc(size); 779 if (!new_addr) 780 return B_NO_MEMORY; 781 } else { 782 new_area = create_area("meta_data_area", &new_addr, B_ANY_ADDRESS, 783 ROUND_UP_TO_PAGE(size), B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 784 if (new_area < 0) 785 return (status_t)new_area; 786 } 787 788 if (meta_data_area > 0) 789 delete_area(meta_data_area); 790 else 791 free(meta_data); 792 793 meta_data = new_addr; 794 meta_data_size = size; 795 meta_data_area = new_area; 796 797 memcpy(meta_data, data, size); 798 799 if (meta_data_area > 0) 800 set_area_protection(meta_data_area, B_READ_AREA); 801 802 return B_OK; 803 } 804 805 806 const void* 807 media_format::MetaData() const 808 { 809 return meta_data; 810 } 811 812 813 int32 814 media_format::MetaDataSize() const 815 { 816 return meta_data_size; 817 } 818 819 820 media_format::media_format() 821 { 822 memset(this, 0x00, sizeof(*this)); 823 meta_data_area = B_BAD_VALUE; 824 } 825 826 827 media_format::media_format(const media_format& other) 828 { 829 memset(this, 0x00, sizeof(*this)); 830 meta_data_area = B_BAD_VALUE; 831 *this = other; 832 } 833 834 835 media_format::~media_format() 836 { 837 if (meta_data_area > 0) 838 delete_area(meta_data_area); 839 else 840 free(meta_data); 841 } 842 843 844 // final 845 media_format& 846 media_format::operator=(const media_format& clone) 847 { 848 // get rid of this format's meta data 849 this->~media_format(); 850 // danger: using only ~media_format() would call the constructor 851 852 // make a binary copy 853 memcpy(this, &clone, sizeof(*this)); 854 // some binary copies are invalid: 855 meta_data = NULL; 856 meta_data_area = B_BAD_VALUE; 857 858 // clone or copy the meta data 859 if (clone.meta_data) { 860 if (clone.meta_data_area != B_BAD_VALUE) { 861 meta_data_area = clone_area("meta_data_clone_area", &meta_data, 862 B_ANY_ADDRESS, B_READ_AREA, clone.meta_data_area); 863 if (meta_data_area < 0) { 864 // whoops, we just lost our meta data 865 meta_data = NULL; 866 meta_data_size = 0; 867 } 868 } else { 869 meta_data = malloc(meta_data_size); 870 if (meta_data) { 871 memcpy(meta_data, clone.meta_data, meta_data_size); 872 } else { 873 // whoops, we just lost our meta data 874 meta_data_size = 0; 875 } 876 } 877 } 878 return *this; 879 } 880 881 882 // #pragma mark - 883 884 885 bool 886 operator==(const media_raw_audio_format& a, const media_raw_audio_format& b) 887 { 888 return a.frame_rate == b.frame_rate 889 && a.channel_count == b.channel_count 890 && a.format == b.format 891 && a.byte_order == b.byte_order 892 && a.buffer_size == b.buffer_size; 893 } 894 895 896 bool 897 operator==(const media_multi_audio_info& a, const media_multi_audio_info& b) 898 { 899 return a.channel_mask == b.channel_mask 900 && a.valid_bits == b.valid_bits 901 && a.matrix_mask == b.matrix_mask; 902 } 903 904 905 bool 906 operator==(const media_multi_audio_format& a, 907 const media_multi_audio_format& b) 908 { 909 return (media_raw_audio_format)a == (media_raw_audio_format)b 910 && (media_multi_audio_info)a == (media_multi_audio_info)b; 911 } 912 913 914 bool 915 operator==(const media_encoded_audio_format& a, 916 const media_encoded_audio_format& b) 917 { 918 return a.output == b.output 919 && a.encoding == b.encoding 920 && a.bit_rate == b.bit_rate 921 && a.frame_size == b.frame_size 922 && a.multi_info == b.multi_info; 923 } 924 925 926 bool 927 operator==(const media_video_display_info& a, 928 const media_video_display_info& b) 929 { 930 return a.format == b.format 931 && a.line_width == b.line_width 932 && a.line_count == b.line_count 933 && a.bytes_per_row == b.bytes_per_row 934 && a.pixel_offset == b.pixel_offset 935 && a.line_offset == b.line_offset 936 && a.flags == b.flags; 937 } 938 939 940 bool 941 operator==(const media_raw_video_format& a, const media_raw_video_format& b) 942 { 943 return a.field_rate == b.field_rate 944 && a.interlace == b.interlace 945 && a.first_active == b.first_active 946 && a.last_active == b.last_active 947 && a.orientation == b.orientation 948 && a.pixel_width_aspect == b.pixel_width_aspect 949 && a.pixel_height_aspect == b.pixel_height_aspect 950 && a.display == b.display; 951 } 952 953 954 bool 955 operator==(const media_encoded_video_format& a, 956 const media_encoded_video_format& b) 957 { 958 return a.output == b.output 959 && a.avg_bit_rate == b.avg_bit_rate 960 && a.max_bit_rate == b.max_bit_rate 961 && a.encoding == b.encoding 962 && a.frame_size == b.frame_size 963 && a.forward_history == b.forward_history 964 && a.backward_history == b.backward_history; 965 } 966 967 968 bool 969 operator==(const media_multistream_format::vid_info& a, 970 const media_multistream_format::vid_info& b) 971 { 972 return a.frame_rate == b.frame_rate 973 && a.width == b.width 974 && a.height == b.height 975 && a.space == b.space 976 && a.sampling_rate == b.sampling_rate 977 && a.sample_format == b.sample_format 978 && a.byte_order == b.byte_order 979 && a.channel_count == b.channel_count; 980 } 981 982 983 bool 984 operator==(const media_multistream_format::avi_info& a, 985 const media_multistream_format::avi_info& b) 986 { 987 return a.us_per_frame == b.us_per_frame 988 && a.width == b.width 989 && a.height == b.height 990 && a.type_count == b.type_count 991 && a.types[0] == b.types[0] 992 && a.types[1] == b.types[1] 993 && a.types[2] == b.types[2] 994 && a.types[3] == b.types[3] 995 && a.types[4] == b.types[4]; 996 } 997 998 999 bool 1000 operator==(const media_multistream_format& a, 1001 const media_multistream_format& b) 1002 { 1003 if (a.avg_bit_rate != b.avg_bit_rate 1004 || a.max_bit_rate != b.max_bit_rate 1005 || a.avg_chunk_size != b.avg_chunk_size 1006 || a.max_chunk_size != b.max_chunk_size 1007 || a.format != b.format 1008 || a.flags != b.flags) { 1009 return false; 1010 } 1011 1012 switch (a.format) { 1013 case media_multistream_format::B_VID: 1014 return a.u.vid == b.u.vid; 1015 1016 case media_multistream_format::B_AVI: 1017 return a.u.avi == b.u.avi; 1018 1019 default: 1020 return true; // TODO: really? 1021 } 1022 } 1023 1024 1025 bool 1026 operator==(const media_format& a, const media_format& b) 1027 { 1028 if (a.type != b.type 1029 || a.user_data_type != b.user_data_type 1030 // TODO: compare user_data[48] ? 1031 || a.require_flags != b.require_flags 1032 || a.deny_flags != b.deny_flags) { 1033 return false; 1034 } 1035 1036 switch (a.type) { 1037 case B_MEDIA_RAW_AUDIO: 1038 return a.u.raw_audio == b.u.raw_audio; 1039 1040 case B_MEDIA_RAW_VIDEO: 1041 return a.u.raw_video == b.u.raw_video; 1042 1043 case B_MEDIA_MULTISTREAM: 1044 return a.u.multistream == b.u.multistream; 1045 1046 case B_MEDIA_ENCODED_AUDIO: 1047 return a.u.encoded_audio == b.u.encoded_audio; 1048 1049 case B_MEDIA_ENCODED_VIDEO: 1050 return a.u.encoded_video == b.u.encoded_video; 1051 1052 default: 1053 return true; // TODO: really? 1054 } 1055 } 1056 1057 1058 // #pragma mark - 1059 1060 1061 /*! return \c true if a and b are compatible (accounting for wildcards) 1062 a is the format you want to feed to something accepting b 1063 */ 1064 bool 1065 format_is_compatible(const media_format& a, const media_format& b) 1066 { 1067 return a.Matches(&b); 1068 } 1069 1070 1071 bool 1072 string_for_format(const media_format& f, char* buf, size_t size) 1073 { 1074 char encoding[10]; /* maybe Be wanted to use some 4CCs ? */ 1075 const char* videoOrientation = "0"; /* I'd use "NC", R5 uses 0. */ 1076 1077 if (buf == NULL) 1078 return false; 1079 switch (f.type) { 1080 case B_MEDIA_RAW_AUDIO: 1081 snprintf(buf, size, 1082 "raw_audio;%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 ";0x%" 1083 B_PRIxSIZE ";0x%#" B_PRIx32 ";%d;0x%04x", 1084 f.u.raw_audio.frame_rate, 1085 f.u.raw_audio.channel_count, 1086 f.u.raw_audio.format, 1087 f.u.raw_audio.byte_order, 1088 f.u.raw_audio.buffer_size, 1089 f.u.raw_audio.channel_mask, 1090 f.u.raw_audio.valid_bits, 1091 f.u.raw_audio.matrix_mask); 1092 return true; 1093 case B_MEDIA_RAW_VIDEO: 1094 if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT) 1095 videoOrientation = "TopLR"; 1096 else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT) 1097 videoOrientation = "BotLR"; 1098 snprintf(buf, size, "raw_video;%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 ";%" 1099 B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d", 1100 f.u.raw_video.field_rate, 1101 f.u.raw_video.display.format, 1102 f.u.raw_video.interlace, 1103 f.u.raw_video.display.line_width, 1104 f.u.raw_video.display.line_count, 1105 f.u.raw_video.first_active, 1106 videoOrientation, 1107 f.u.raw_video.pixel_width_aspect, 1108 f.u.raw_video.pixel_height_aspect); 1109 return true; 1110 case B_MEDIA_ENCODED_AUDIO: 1111 snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding); 1112 snprintf(buf, size, 1113 "caudio;%s;%g;%ld;(%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 1114 ";0x%" B_PRIxSIZE ";0x%08" B_PRIx32 ";%d;0x%04x)", 1115 encoding, 1116 f.u.encoded_audio.bit_rate, 1117 f.u.encoded_audio.frame_size, 1118 f.u.encoded_audio.output.frame_rate, 1119 f.u.encoded_audio.output.channel_count, 1120 f.u.encoded_audio.output.format, 1121 f.u.encoded_audio.output.byte_order, 1122 f.u.encoded_audio.output.buffer_size, 1123 f.u.encoded_audio.multi_info.channel_mask, 1124 f.u.encoded_audio.multi_info.valid_bits, 1125 f.u.encoded_audio.multi_info.matrix_mask); 1126 return true; 1127 case B_MEDIA_ENCODED_VIDEO: 1128 snprintf(encoding, 10, "%d", f.u.encoded_video.encoding); 1129 if (f.u.encoded_video.output.orientation == B_VIDEO_TOP_LEFT_RIGHT) 1130 videoOrientation = "TopLR"; 1131 else if (f.u.encoded_video.output.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT) 1132 videoOrientation = "BotLR"; 1133 snprintf(buf, size, 1134 "cvideo;%s;%g;%g;%" B_PRIuSIZE ";(%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 1135 ";%" B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d)", 1136 encoding, 1137 f.u.encoded_video.avg_bit_rate, 1138 f.u.encoded_video.max_bit_rate, 1139 f.u.encoded_video.frame_size, 1140 f.u.encoded_video.output.field_rate, 1141 f.u.encoded_video.output.display.format, 1142 f.u.encoded_video.output.interlace, 1143 f.u.encoded_video.output.display.line_width, 1144 f.u.encoded_video.output.display.line_count, 1145 f.u.encoded_video.output.first_active, 1146 videoOrientation, 1147 f.u.encoded_video.output.pixel_width_aspect, 1148 f.u.encoded_video.output.pixel_height_aspect); 1149 return true; 1150 default: 1151 snprintf(buf, size, "%d-", f.type); 1152 unsigned char* p = (unsigned char*)&(f.u); 1153 size -= strlen(buf); 1154 buf += strlen(buf); 1155 for (int i = 0; (size > 2) && (i < 96); i++) { 1156 snprintf(buf, 3, "%2.2x", *(p + i)); 1157 buf+=2; 1158 size-=2; 1159 } 1160 return true; // ? 1161 } 1162 return false; 1163 } 1164 1165 1166 // #pragma mark - 1167 1168 1169 bool 1170 operator==(const media_file_format_id& a, const media_file_format_id& b) 1171 { 1172 return a.node == b.node && a.device == b.device 1173 && a.internal_id == b.internal_id; 1174 } 1175 1176 1177 bool 1178 operator<(const media_file_format_id& a, const media_file_format_id& b) 1179 { 1180 return a.internal_id < b.internal_id; 1181 } 1182 1183 1184 // #pragma mark - 1185 1186 1187 //! Use this function to iterate through available file format writers. 1188 status_t 1189 get_next_file_format(int32* cookie, media_file_format* mff) 1190 { 1191 if (cookie == NULL || mff == NULL) 1192 return B_BAD_VALUE; 1193 1194 // get list of available readers from the server 1195 server_get_file_format_request request; 1196 request.cookie = *cookie; 1197 server_get_file_format_reply reply; 1198 status_t ret = QueryServer(SERVER_GET_FILE_FORMAT_FOR_COOKIE, &request, 1199 sizeof(request), &reply, sizeof(reply)); 1200 if (ret != B_OK) 1201 return ret; 1202 1203 *cookie = *cookie + 1; 1204 *mff = reply.file_format; 1205 1206 return B_OK; 1207 } 1208 1209 1210 // #pragma mark - 1211 1212 1213 // final & verified 1214 const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server"; 1215 const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host"; 1216 1217 const type_code B_CODEC_TYPE_INFO = 0x040807b2; 1218 1219 1220 // #pragma mark - 1221 1222 1223 // shutdown_media_server() and launch_media_server() 1224 // are provided by libbe.so in BeOS R5 1225 1226 status_t 1227 shutdown_media_server(bigtime_t timeout, 1228 bool (*progress)(int stage, const char* message, void* cookie), 1229 void* cookie) 1230 { 1231 BMessage msg(B_QUIT_REQUESTED); 1232 BMessage reply; 1233 status_t err; 1234 1235 if ((err = msg.AddBool("be:_user_request", true)) != B_OK) 1236 return err; 1237 1238 if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) { 1239 BMessenger messenger(B_MEDIA_SERVER_SIGNATURE); 1240 progress(10, "Telling media_server to quit.", cookie); 1241 1242 err = messenger.SendMessage(&msg, &reply, 2000000, 2000000); 1243 if (err != B_OK) 1244 return err; 1245 1246 int32 rv; 1247 if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK) 1248 return rv; 1249 } 1250 1251 if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) { 1252 BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE); 1253 progress(20, "Telling media_addon_server to quit.", cookie); 1254 1255 err = messenger.SendMessage(&msg, &reply, 2000000, 2000000); 1256 if (err != B_OK) 1257 return err; 1258 1259 int32 rv; 1260 if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK) 1261 return rv; 1262 } 1263 1264 if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) { 1265 progress(40, "Waiting for media_server to quit.", cookie); 1266 snooze(200000); 1267 } 1268 1269 if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) { 1270 progress(50, "Waiting for media_addon_server to quit.", cookie); 1271 snooze(200000); 1272 } 1273 1274 progress(70, "Cleaning Up.", cookie); 1275 snooze(1000000); 1276 1277 if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) { 1278 kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE)); 1279 } 1280 1281 if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) { 1282 kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE)); 1283 } 1284 1285 progress(100, "Done Shutting Down.", cookie); 1286 snooze(1000000); 1287 1288 return B_OK; 1289 } 1290 1291 1292 status_t 1293 launch_media_server(uint32 flags) 1294 { 1295 status_t err; 1296 1297 if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) 1298 return B_ALREADY_RUNNING; 1299 1300 if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) { 1301 kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE)); 1302 snooze(1000000); 1303 } 1304 1305 err = be_roster->Launch(B_MEDIA_SERVER_SIGNATURE); 1306 if (err != B_OK) 1307 return err; 1308 1309 err = B_MEDIA_SYSTEM_FAILURE; 1310 for (int i = 0; i < 15; i++) { 1311 snooze(2000000); 1312 1313 BMessage msg(1); // this is a hack 1314 BMessage reply; 1315 BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE); 1316 1317 if (messenger.IsValid()) { 1318 messenger.SendMessage(&msg, &reply, 2000000, 2000000); 1319 err = B_OK; 1320 break; 1321 } 1322 } 1323 1324 return err; 1325 } 1326 1327 1328 // #pragma mark - 1329 1330 1331 // Given an image_id, prepare that image_id for realtime media 1332 // If the kind of media indicated by "flags" is not enabled for real-time, 1333 // B_MEDIA_REALTIME_DISABLED is returned. 1334 // If there are not enough system resources to enable real-time performance, 1335 // B_MEDIA_REALTIME_UNAVAILABLE is returned. 1336 status_t 1337 media_realtime_init_image(image_id image, uint32 flags) 1338 { 1339 UNIMPLEMENTED(); 1340 return B_OK; 1341 } 1342 1343 // Given a thread ID, and an optional indication of what the thread is 1344 // doing in "flags", prepare the thread for real-time media performance. 1345 // Currently, this means locking the thread stack, up to size_used bytes, 1346 // or all of it if 0 is passed. Typically, you will not be using all 1347 // 256 kB of the stack, so you should pass some smaller value you determine 1348 // from profiling the thread; typically in the 32-64kB range. 1349 // Return values are the same as for media_prepare_realtime_image(). 1350 status_t 1351 media_realtime_init_thread(thread_id thread, size_t stack_used, uint32 flags) 1352 { 1353 UNIMPLEMENTED(); 1354 return B_OK; 1355 } 1356 1357 1358 // #pragma mark - media_encode_info 1359 1360 1361 media_encode_info::media_encode_info() 1362 { 1363 flags = 0; 1364 used_data_size = 0; 1365 start_time = 0; 1366 time_to_encode = INT64_MAX; 1367 file_format_data = NULL; 1368 file_format_data_size = 0; 1369 codec_data = NULL; 1370 codec_data_size = 0; 1371 } 1372 1373 1374 media_decode_info::media_decode_info() 1375 { 1376 time_to_decode = INT64_MAX; 1377 file_format_data = NULL; 1378 file_format_data_size = 0; 1379 codec_data = NULL; 1380 codec_data_size = 0; 1381 } 1382 1383 1384