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