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