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