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 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 > 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 void 836 media_format::Unflatten(const char *flatBuffer) 837 { 838 // TODO: we should not!!! make flat copies of media_format 839 memcpy(this, flatBuffer, sizeof(*this)); 840 meta_data = NULL; 841 meta_data_area = B_BAD_VALUE; 842 } 843 844 845 void 846 media_format::Clear() 847 { 848 memset(this, 0x00, sizeof(*this)); 849 meta_data = NULL; 850 meta_data_area = B_BAD_VALUE; 851 } 852 853 854 media_format::media_format() 855 { 856 this->Clear(); 857 } 858 859 860 media_format::media_format(const media_format& other) 861 { 862 this->Clear(); 863 *this = other; 864 } 865 866 867 media_format::~media_format() 868 { 869 if (meta_data_area > 0) 870 delete_area(meta_data_area); 871 else 872 free(meta_data); 873 } 874 875 876 // final 877 media_format& 878 media_format::operator=(const media_format& clone) 879 { 880 // get rid of this format's meta data 881 this->~media_format(); 882 // danger: using only ~media_format() would call the constructor 883 884 // make a binary copy 885 memcpy(this, &clone, sizeof(*this)); 886 // some binary copies are invalid: 887 meta_data = NULL; 888 meta_data_area = B_BAD_VALUE; 889 890 // clone or copy the meta data 891 if (clone.meta_data) { 892 if (clone.meta_data_area != B_BAD_VALUE) { 893 meta_data_area = clone_area("meta_data_clone_area", &meta_data, 894 B_ANY_ADDRESS, B_READ_AREA, clone.meta_data_area); 895 if (meta_data_area < 0) { 896 // whoops, we just lost our meta data 897 meta_data = NULL; 898 meta_data_size = 0; 899 } 900 } else { 901 meta_data = malloc(meta_data_size); 902 if (meta_data) { 903 memcpy(meta_data, clone.meta_data, meta_data_size); 904 } else { 905 // whoops, we just lost our meta data 906 meta_data_size = 0; 907 } 908 } 909 } 910 return *this; 911 } 912 913 914 // #pragma mark - 915 916 917 bool 918 operator==(const media_raw_audio_format& a, const media_raw_audio_format& b) 919 { 920 return a.frame_rate == b.frame_rate 921 && a.channel_count == b.channel_count 922 && a.format == b.format 923 && a.byte_order == b.byte_order 924 && a.buffer_size == b.buffer_size; 925 } 926 927 928 bool 929 operator==(const media_multi_audio_info& a, const media_multi_audio_info& b) 930 { 931 return a.channel_mask == b.channel_mask 932 && a.valid_bits == b.valid_bits 933 && a.matrix_mask == b.matrix_mask; 934 } 935 936 937 bool 938 operator==(const media_multi_audio_format& a, 939 const media_multi_audio_format& b) 940 { 941 return (media_raw_audio_format)a == (media_raw_audio_format)b 942 && (media_multi_audio_info)a == (media_multi_audio_info)b; 943 } 944 945 946 bool 947 operator==(const media_encoded_audio_format& a, 948 const media_encoded_audio_format& b) 949 { 950 return a.output == b.output 951 && a.encoding == b.encoding 952 && a.bit_rate == b.bit_rate 953 && a.frame_size == b.frame_size 954 && a.multi_info == b.multi_info; 955 } 956 957 958 bool 959 operator==(const media_video_display_info& a, 960 const media_video_display_info& b) 961 { 962 return a.format == b.format 963 && a.line_width == b.line_width 964 && a.line_count == b.line_count 965 && a.bytes_per_row == b.bytes_per_row 966 && a.pixel_offset == b.pixel_offset 967 && a.line_offset == b.line_offset 968 && a.flags == b.flags; 969 } 970 971 972 bool 973 operator==(const media_raw_video_format& a, const media_raw_video_format& b) 974 { 975 return a.field_rate == b.field_rate 976 && a.interlace == b.interlace 977 && a.first_active == b.first_active 978 && a.last_active == b.last_active 979 && a.orientation == b.orientation 980 && a.pixel_width_aspect == b.pixel_width_aspect 981 && a.pixel_height_aspect == b.pixel_height_aspect 982 && a.display == b.display; 983 } 984 985 986 bool 987 operator==(const media_encoded_video_format& a, 988 const media_encoded_video_format& b) 989 { 990 return a.output == b.output 991 && a.avg_bit_rate == b.avg_bit_rate 992 && a.max_bit_rate == b.max_bit_rate 993 && a.encoding == b.encoding 994 && a.frame_size == b.frame_size 995 && a.forward_history == b.forward_history 996 && a.backward_history == b.backward_history; 997 } 998 999 1000 bool 1001 operator==(const media_multistream_format::vid_info& a, 1002 const media_multistream_format::vid_info& b) 1003 { 1004 return a.frame_rate == b.frame_rate 1005 && a.width == b.width 1006 && a.height == b.height 1007 && a.space == b.space 1008 && a.sampling_rate == b.sampling_rate 1009 && a.sample_format == b.sample_format 1010 && a.byte_order == b.byte_order 1011 && a.channel_count == b.channel_count; 1012 } 1013 1014 1015 bool 1016 operator==(const media_multistream_format::avi_info& a, 1017 const media_multistream_format::avi_info& b) 1018 { 1019 return a.us_per_frame == b.us_per_frame 1020 && a.width == b.width 1021 && a.height == b.height 1022 && a.type_count == b.type_count 1023 && a.types[0] == b.types[0] 1024 && a.types[1] == b.types[1] 1025 && a.types[2] == b.types[2] 1026 && a.types[3] == b.types[3] 1027 && a.types[4] == b.types[4]; 1028 } 1029 1030 1031 bool 1032 operator==(const media_multistream_format& a, 1033 const media_multistream_format& b) 1034 { 1035 if (a.avg_bit_rate != b.avg_bit_rate 1036 || a.max_bit_rate != b.max_bit_rate 1037 || a.avg_chunk_size != b.avg_chunk_size 1038 || a.max_chunk_size != b.max_chunk_size 1039 || a.format != b.format 1040 || a.flags != b.flags) { 1041 return false; 1042 } 1043 1044 switch (a.format) { 1045 case media_multistream_format::B_VID: 1046 return a.u.vid == b.u.vid; 1047 1048 case media_multistream_format::B_AVI: 1049 return a.u.avi == b.u.avi; 1050 1051 default: 1052 return true; // TODO: really? 1053 } 1054 } 1055 1056 1057 bool 1058 operator==(const media_format& a, const media_format& b) 1059 { 1060 if (a.type != b.type 1061 || a.user_data_type != b.user_data_type 1062 // TODO: compare user_data[48] ? 1063 || a.require_flags != b.require_flags 1064 || a.deny_flags != b.deny_flags) { 1065 return false; 1066 } 1067 1068 switch (a.type) { 1069 case B_MEDIA_RAW_AUDIO: 1070 return a.u.raw_audio == b.u.raw_audio; 1071 1072 case B_MEDIA_RAW_VIDEO: 1073 return a.u.raw_video == b.u.raw_video; 1074 1075 case B_MEDIA_MULTISTREAM: 1076 return a.u.multistream == b.u.multistream; 1077 1078 case B_MEDIA_ENCODED_AUDIO: 1079 return a.u.encoded_audio == b.u.encoded_audio; 1080 1081 case B_MEDIA_ENCODED_VIDEO: 1082 return a.u.encoded_video == b.u.encoded_video; 1083 1084 default: 1085 return true; // TODO: really? 1086 } 1087 } 1088 1089 1090 // #pragma mark - 1091 1092 1093 /*! return \c true if a and b are compatible (accounting for wildcards) 1094 a is the format you want to feed to something accepting b 1095 */ 1096 bool 1097 format_is_compatible(const media_format& a, const media_format& b) 1098 { 1099 return a.Matches(&b); 1100 } 1101 1102 1103 bool 1104 string_for_format(const media_format& f, char* buf, size_t size) 1105 { 1106 char encoding[10]; /* maybe Be wanted to use some 4CCs ? */ 1107 const char* videoOrientation = "0"; /* I'd use "NC", R5 uses 0. */ 1108 1109 if (buf == NULL) 1110 return false; 1111 switch (f.type) { 1112 case B_MEDIA_RAW_AUDIO: 1113 snprintf(buf, size, 1114 "raw_audio;%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 ";0x%" 1115 B_PRIxSIZE ";0x%#" B_PRIx32 ";%d;0x%04x", 1116 f.u.raw_audio.frame_rate, 1117 f.u.raw_audio.channel_count, 1118 f.u.raw_audio.format, 1119 f.u.raw_audio.byte_order, 1120 f.u.raw_audio.buffer_size, 1121 f.u.raw_audio.channel_mask, 1122 f.u.raw_audio.valid_bits, 1123 f.u.raw_audio.matrix_mask); 1124 return true; 1125 case B_MEDIA_RAW_VIDEO: 1126 if (f.u.raw_video.orientation == B_VIDEO_TOP_LEFT_RIGHT) 1127 videoOrientation = "TopLR"; 1128 else if (f.u.raw_video.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT) 1129 videoOrientation = "BotLR"; 1130 snprintf(buf, size, "raw_video;%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 ";%" 1131 B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d", 1132 f.u.raw_video.field_rate, 1133 f.u.raw_video.display.format, 1134 f.u.raw_video.interlace, 1135 f.u.raw_video.display.line_width, 1136 f.u.raw_video.display.line_count, 1137 f.u.raw_video.first_active, 1138 videoOrientation, 1139 f.u.raw_video.pixel_width_aspect, 1140 f.u.raw_video.pixel_height_aspect); 1141 return true; 1142 case B_MEDIA_ENCODED_AUDIO: 1143 snprintf(encoding, 10, "%d", f.u.encoded_audio.encoding); 1144 snprintf(buf, size, 1145 "caudio;%s;%g;%ld;(%g;%" B_PRIu32 ";0x%" B_PRIx32 ";%" B_PRIu32 1146 ";0x%" B_PRIxSIZE ";0x%08" B_PRIx32 ";%d;0x%04x)", 1147 encoding, 1148 f.u.encoded_audio.bit_rate, 1149 f.u.encoded_audio.frame_size, 1150 f.u.encoded_audio.output.frame_rate, 1151 f.u.encoded_audio.output.channel_count, 1152 f.u.encoded_audio.output.format, 1153 f.u.encoded_audio.output.byte_order, 1154 f.u.encoded_audio.output.buffer_size, 1155 f.u.encoded_audio.multi_info.channel_mask, 1156 f.u.encoded_audio.multi_info.valid_bits, 1157 f.u.encoded_audio.multi_info.matrix_mask); 1158 return true; 1159 case B_MEDIA_ENCODED_VIDEO: 1160 snprintf(encoding, 10, "%d", f.u.encoded_video.encoding); 1161 if (f.u.encoded_video.output.orientation == B_VIDEO_TOP_LEFT_RIGHT) 1162 videoOrientation = "TopLR"; 1163 else if (f.u.encoded_video.output.orientation == B_VIDEO_BOTTOM_LEFT_RIGHT) 1164 videoOrientation = "BotLR"; 1165 snprintf(buf, size, 1166 "cvideo;%s;%g;%g;%" B_PRIuSIZE ";(%g;0x%x;%" B_PRIu32 ";%" B_PRIu32 1167 ";%" B_PRIu32 ";%" B_PRIu32 ";%s;%d;%d)", 1168 encoding, 1169 f.u.encoded_video.avg_bit_rate, 1170 f.u.encoded_video.max_bit_rate, 1171 f.u.encoded_video.frame_size, 1172 f.u.encoded_video.output.field_rate, 1173 f.u.encoded_video.output.display.format, 1174 f.u.encoded_video.output.interlace, 1175 f.u.encoded_video.output.display.line_width, 1176 f.u.encoded_video.output.display.line_count, 1177 f.u.encoded_video.output.first_active, 1178 videoOrientation, 1179 f.u.encoded_video.output.pixel_width_aspect, 1180 f.u.encoded_video.output.pixel_height_aspect); 1181 return true; 1182 default: 1183 snprintf(buf, size, "%d-", f.type); 1184 unsigned char* p = (unsigned char*)&(f.u); 1185 size -= strlen(buf); 1186 buf += strlen(buf); 1187 for (int i = 0; (size > 2) && (i < 96); i++) { 1188 snprintf(buf, 3, "%2.2x", *(p + i)); 1189 buf+=2; 1190 size-=2; 1191 } 1192 return true; // ? 1193 } 1194 return false; 1195 } 1196 1197 1198 // #pragma mark - 1199 1200 1201 bool 1202 operator==(const media_file_format_id& a, const media_file_format_id& b) 1203 { 1204 return a.node == b.node && a.device == b.device 1205 && a.internal_id == b.internal_id; 1206 } 1207 1208 1209 bool 1210 operator<(const media_file_format_id& a, const media_file_format_id& b) 1211 { 1212 return a.internal_id < b.internal_id; 1213 } 1214 1215 1216 // #pragma mark - 1217 1218 1219 //! Use this function to iterate through available file format writers. 1220 status_t 1221 get_next_file_format(int32* cookie, media_file_format* mff) 1222 { 1223 if (cookie == NULL || mff == NULL) 1224 return B_BAD_VALUE; 1225 1226 status_t ret = AddOnManager::GetInstance()->GetFileFormat(mff, *cookie); 1227 if (ret != B_OK) 1228 return ret; 1229 1230 *cookie = *cookie + 1; 1231 1232 return B_OK; 1233 } 1234 1235 1236 // #pragma mark - 1237 1238 1239 // final & verified 1240 const char* B_MEDIA_SERVER_SIGNATURE = "application/x-vnd.Be.media-server"; 1241 const char* B_MEDIA_ADDON_SERVER_SIGNATURE = "application/x-vnd.Be.addon-host"; 1242 1243 const type_code B_CODEC_TYPE_INFO = 0x040807b2; 1244 1245 1246 // #pragma mark - 1247 1248 1249 // shutdown_media_server() and launch_media_server() 1250 // are provided by libbe.so in BeOS R5 1251 1252 #define MEDIA_SERVICE_NOTIFICATION_ID "MediaServiceNotificationID" 1253 1254 1255 void 1256 notify_system(float progress, const char* message) 1257 { 1258 BNotification notification(B_PROGRESS_NOTIFICATION); 1259 notification.SetMessageID(MEDIA_SERVICE_NOTIFICATION_ID); 1260 notification.SetProgress(progress); 1261 notification.SetGroup(B_TRANSLATE("Media Service")); 1262 notification.SetContent(message); 1263 1264 app_info info; 1265 be_app->GetAppInfo(&info); 1266 BBitmap icon(BRect(0, 0, 32, 32), B_RGBA32); 1267 BNode node(&info.ref); 1268 BIconUtils::GetVectorIcon(&node, "BEOS:ICON", &icon); 1269 notification.SetIcon(&icon); 1270 1271 notification.Send(); 1272 } 1273 1274 1275 void 1276 progress_shutdown(int stage, 1277 bool (*progress)(int stage, const char* message, void* cookie), 1278 void* cookie) 1279 { 1280 // parameter "message" is no longer used. It is kept for compatibility with 1281 // BeOS as this is used as a shutdown_media_server callback. 1282 1283 TRACE("stage: %i\n", stage); 1284 const char* string = "Unknown stage"; 1285 switch (stage) { 1286 case 10: 1287 string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS); 1288 break; 1289 case 20: 1290 string = B_TRANSLATE("Waiting for media_server to quit."); 1291 break; 1292 case 40: 1293 string = B_TRANSLATE("Telling media_addon_server to quit."); 1294 break; 1295 case 50: 1296 string = B_TRANSLATE("Waiting for media_addon_server to quit."); 1297 break; 1298 case 70: 1299 string = B_TRANSLATE("Cleaning up."); 1300 break; 1301 case 100: 1302 string = B_TRANSLATE("Done shutting down."); 1303 break; 1304 } 1305 1306 if (progress == NULL) 1307 notify_system(stage / 100.0f, string); 1308 else 1309 progress(stage, string, cookie); 1310 } 1311 1312 1313 status_t 1314 shutdown_media_server(bigtime_t timeout, 1315 bool (*progress)(int stage, const char* message, void* cookie), 1316 void* cookie) 1317 { 1318 BLaunchRoster launchRoster; 1319 launchRoster.StopTarget(B_MEDIA_SERVER_SIGNATURE); 1320 1321 BMessage msg(B_QUIT_REQUESTED); 1322 status_t err = B_MEDIA_SYSTEM_FAILURE; 1323 bool shutdown = false; 1324 1325 BMediaRoster* roster = BMediaRoster::Roster(&err); 1326 if (roster == NULL || err != B_OK) 1327 return err; 1328 1329 if (progress == NULL && roster->Lock()) { 1330 MediaRosterEx(roster)->EnableLaunchNotification(true, true); 1331 roster->Unlock(); 1332 } 1333 1334 if ((err = msg.AddBool("be:_user_request", true)) != B_OK) 1335 return err; 1336 1337 team_id mediaServer = be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE); 1338 team_id addOnServer = be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE); 1339 1340 if (mediaServer != B_ERROR) { 1341 BMessage reply; 1342 BMessenger messenger(B_MEDIA_SERVER_SIGNATURE, mediaServer); 1343 progress_shutdown(10, progress, cookie); 1344 1345 err = messenger.SendMessage(&msg, &reply, 2000000, 2000000); 1346 reply.FindBool("_shutdown", &shutdown); 1347 if (err == B_TIMED_OUT || shutdown == false) { 1348 if (messenger.IsValid()) 1349 kill_team(mediaServer); 1350 } else if (err != B_OK) 1351 return err; 1352 1353 progress_shutdown(20, progress, cookie); 1354 1355 int32 rv; 1356 if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK) 1357 return rv; 1358 } 1359 1360 if (addOnServer != B_ERROR) { 1361 shutdown = false; 1362 BMessage reply; 1363 BMessenger messenger(B_MEDIA_ADDON_SERVER_SIGNATURE, addOnServer); 1364 progress_shutdown(40, progress, cookie); 1365 1366 // The media_server usually shutdown the media_addon_server, 1367 // if not let's do something. 1368 if (messenger.IsValid()) { 1369 err = messenger.SendMessage(&msg, &reply, 2000000, 2000000); 1370 reply.FindBool("_shutdown", &shutdown); 1371 if (err == B_TIMED_OUT || shutdown == false) { 1372 if (messenger.IsValid()) 1373 kill_team(addOnServer); 1374 } else if (err != B_OK) 1375 return err; 1376 1377 progress_shutdown(50, progress, cookie); 1378 1379 int32 rv; 1380 if (reply.FindInt32("error", &rv) == B_OK && rv != B_OK) 1381 return rv; 1382 } 1383 } 1384 1385 progress_shutdown(100, progress, cookie); 1386 return B_OK; 1387 } 1388 1389 1390 void 1391 progress_startup(int stage, 1392 bool (*progress)(int stage, const char* message, void* cookie), 1393 void* cookie) 1394 { 1395 // parameter "message" is no longer used. It is kept for compatibility with 1396 // BeOS as this is used as a shutdown_media_server callback. 1397 1398 TRACE("stage: %i\n", stage); 1399 const char* string = "Unknown stage"; 1400 switch (stage) { 1401 case 10: 1402 string = B_TRANSLATE("Stopping media server" B_UTF8_ELLIPSIS); 1403 break; 1404 case 20: 1405 string = B_TRANSLATE("Stopping media_addon_server."); 1406 break; 1407 case 50: 1408 string = B_TRANSLATE("Starting media_services."); 1409 break; 1410 case 90: 1411 string = B_TRANSLATE("Error occurred starting media services."); 1412 break; 1413 case 100: 1414 string = B_TRANSLATE("Ready for use."); 1415 break; 1416 } 1417 1418 if (progress == NULL) 1419 notify_system(stage / 100.0f, string); 1420 else 1421 progress(stage, string, cookie); 1422 } 1423 1424 1425 status_t 1426 launch_media_server(bigtime_t timeout, 1427 bool (*progress)(int stage, const char* message, void* cookie), 1428 void* cookie, uint32 flags) 1429 { 1430 if (BMediaRoster::IsRunning()) 1431 return B_ALREADY_RUNNING; 1432 1433 status_t err = B_MEDIA_SYSTEM_FAILURE; 1434 BMediaRoster* roster = BMediaRoster::Roster(&err); 1435 if (roster == NULL || err != B_OK) 1436 return err; 1437 1438 if (progress == NULL && roster->Lock()) { 1439 MediaRosterEx(roster)->EnableLaunchNotification(true, true); 1440 roster->Unlock(); 1441 } 1442 1443 // The media_server crashed 1444 if (be_roster->IsRunning(B_MEDIA_ADDON_SERVER_SIGNATURE)) { 1445 progress_startup(10, progress, cookie); 1446 kill_team(be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE)); 1447 } 1448 1449 // The media_addon_server crashed 1450 if (be_roster->IsRunning(B_MEDIA_SERVER_SIGNATURE)) { 1451 progress_startup(20, progress, cookie); 1452 kill_team(be_roster->TeamFor(B_MEDIA_SERVER_SIGNATURE)); 1453 } 1454 1455 progress_startup(50, progress, cookie); 1456 1457 err = BLaunchRoster().Start(B_MEDIA_SERVER_SIGNATURE); 1458 1459 if (err != B_OK) 1460 progress_startup(90, progress, cookie); 1461 else if (progress != NULL) { 1462 progress_startup(100, progress, cookie); 1463 err = B_OK; 1464 } 1465 1466 return err; 1467 } 1468 1469 1470 // #pragma mark - media_encode_info 1471 1472 1473 media_encode_info::media_encode_info() 1474 { 1475 flags = 0; 1476 used_data_size = 0; 1477 start_time = 0; 1478 time_to_encode = INT64_MAX; 1479 file_format_data = NULL; 1480 file_format_data_size = 0; 1481 codec_data = NULL; 1482 codec_data_size = 0; 1483 } 1484 1485 1486 media_decode_info::media_decode_info() 1487 { 1488 time_to_decode = INT64_MAX; 1489 file_format_data = NULL; 1490 file_format_data_size = 0; 1491 codec_data = NULL; 1492 codec_data_size = 0; 1493 } 1494 1495 1496