| 443 | } |
| 444 | |
| 445 | static av_cold int pulse_write_header(AVFormatContext *h) |
| 446 | { |
| 447 | PulseData *s = h->priv_data; |
| 448 | AVStream *st = NULL; |
| 449 | int ret; |
| 450 | pa_sample_spec sample_spec; |
| 451 | pa_buffer_attr buffer_attributes = { -1, -1, -1, -1, -1 }; |
| 452 | pa_channel_map channel_map; |
| 453 | pa_mainloop_api *mainloop_api; |
| 454 | const char *stream_name = s->stream_name; |
| 455 | static const pa_stream_flags_t stream_flags = PA_STREAM_INTERPOLATE_TIMING | |
| 456 | PA_STREAM_AUTO_TIMING_UPDATE | |
| 457 | PA_STREAM_NOT_MONOTONIC; |
| 458 | |
| 459 | if (h->nb_streams != 1 || h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) { |
| 460 | av_log(s, AV_LOG_ERROR, "Only a single audio stream is supported.\n"); |
| 461 | return AVERROR(EINVAL); |
| 462 | } |
| 463 | st = h->streams[0]; |
| 464 | |
| 465 | if (!stream_name) { |
| 466 | if (h->url[0]) |
| 467 | stream_name = h->url; |
| 468 | else |
| 469 | stream_name = "Playback"; |
| 470 | } |
| 471 | s->nonblocking = (h->flags & AVFMT_FLAG_NONBLOCK); |
| 472 | |
| 473 | if (s->buffer_duration) { |
| 474 | int64_t bytes = av_rescale(s->buffer_duration, |
| 475 | st->codecpar->ch_layout.nb_channels * |
| 476 | (int64_t)st->codecpar->sample_rate * |
| 477 | av_get_bytes_per_sample(st->codecpar->format), |
| 478 | 1000); |
| 479 | buffer_attributes.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1)); |
| 480 | av_log(s, AV_LOG_DEBUG, |
| 481 | "Buffer duration: %ums recalculated into %"PRId64" bytes buffer.\n", |
| 482 | s->buffer_duration, bytes); |
| 483 | av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", buffer_attributes.tlength); |
| 484 | } else if (s->buffer_size) |
| 485 | buffer_attributes.tlength = s->buffer_size; |
| 486 | if (s->prebuf) |
| 487 | buffer_attributes.prebuf = s->prebuf; |
| 488 | if (s->minreq) |
| 489 | buffer_attributes.minreq = s->minreq; |
| 490 | |
| 491 | sample_spec.format = ff_codec_id_to_pulse_format(st->codecpar->codec_id); |
| 492 | sample_spec.rate = st->codecpar->sample_rate; |
| 493 | sample_spec.channels = st->codecpar->ch_layout.nb_channels; |
| 494 | if (!pa_sample_spec_valid(&sample_spec)) { |
| 495 | av_log(s, AV_LOG_ERROR, "Invalid sample spec.\n"); |
| 496 | return AVERROR(EINVAL); |
| 497 | } |
| 498 | |
| 499 | if (sample_spec.channels == 1) { |
| 500 | channel_map.channels = 1; |
| 501 | channel_map.map[0] = PA_CHANNEL_POSITION_MONO; |
| 502 | } else if (st->codecpar->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { |
nothing calls this directly
no test coverage detected