Merge remote-tracking branch 'lukaszmluki/master'

* lukaszmluki/master:
  lavd/pulse_audio_enc: respect minreq while checking buffer fullness
  lavd/pulse_audio_enc: signal that buffer is still writable after write
  lavd/pulse_audio_enc: add pointer checks
  lavd/pulse_audio_enc: add more buffer attributes
  lavd/fbdev_dec: implement fbdev_get_device_list callback
  lavd/fbdev_enc: move list device code to fbdev_common
  lavd/fbdev_enc: remove redundant assignments

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2014-04-30 14:34:55 +02:00
commit bb6d00f014
6 changed files with 112 additions and 61 deletions

View File

@ -290,6 +290,20 @@ When both options are provided then the highest value is used
are set to 0 (which is default), the device will use the default
PulseAudio duration value. By default PulseAudio set buffer duration
to around 2 seconds.
@item prebuf
Specify pre-buffering size in bytes. The server does not start with
playback before at least @option{prebuf} bytes are available in the
buffer. By default this option is initialized to the same value as
@option{buffer_size} or @option{buffer_duration} (whichever is bigger).
@item minreq
Specify minimum request size in bytes. The server does not request less
than @option{minreq} bytes from the client, instead waits until the buffer
is free enough to request more bytes at once. It is recommended to not set
this option, which will initialize this to a value that is deemed sensible
by the server.
@end table
@subsection Examples

View File

@ -20,9 +20,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include "fbdev_common.h"
#include "libavutil/common.h"
#include "avdevice.h"
struct rgb_pixfmt_map_entry {
int bits_per_pixel;
@ -65,3 +69,61 @@ const char* ff_fbdev_default_device()
return dev;
}
int ff_fbdev_get_device_list(AVDeviceInfoList *device_list)
{
struct fb_var_screeninfo varinfo;
struct fb_fix_screeninfo fixinfo;
char device_file[12];
AVDeviceInfo *device = NULL;
int i, fd, ret = 0;
const char *default_device = ff_fbdev_default_device();
if (!device_list)
return AVERROR(EINVAL);
for (i = 0; i <= 31; i++) {
snprintf(device_file, sizeof(device_file), "/dev/fb%d", i);
if ((fd = avpriv_open(device_file, O_RDWR)) < 0)
continue;
if (ioctl(fd, FBIOGET_VSCREENINFO, &varinfo) == -1)
goto fail_device;
if (ioctl(fd, FBIOGET_FSCREENINFO, &fixinfo) == -1)
goto fail_device;
device = av_mallocz(sizeof(AVDeviceInfo));
if (!device) {
ret = AVERROR(ENOMEM);
goto fail_device;
}
device->device_name = av_strdup(device_file);
device->device_description = av_strdup(fixinfo.id);
if (!device->device_name || !device->device_description) {
ret = AVERROR(ENOMEM);
goto fail_device;
}
if ((ret = av_dynarray_add_nofree(&device_list->devices,
&device_list->nb_devices, device)) < 0)
goto fail_device;
if (default_device && !strcmp(device->device_name, default_device)) {
device_list->default_device = device_list->nb_devices - 1;
default_device = NULL;
}
close(fd);
continue;
fail_device:
if (device) {
av_free(device->device_name);
av_free(device->device_description);
av_freep(&device);
}
if (fd >= 0)
close(fd);
if (ret < 0)
return ret;
}
return 0;
}

View File

@ -27,8 +27,12 @@
#include <linux/fb.h>
#include "libavutil/pixfmt.h"
struct AVDeviceInfoList;
enum AVPixelFormat ff_get_pixfmt_from_fb_varinfo(struct fb_var_screeninfo *varinfo);
const char* ff_fbdev_default_device(void);
int ff_fbdev_get_device_list(struct AVDeviceInfoList *device_list);
#endif /* AVDEVICE_FBDEV_COMMON_H */

View File

@ -205,6 +205,11 @@ static av_cold int fbdev_read_close(AVFormatContext *avctx)
return 0;
}
static int fbdev_get_device_list(AVFormatContext *s, AVDeviceInfoList *device_list)
{
return ff_fbdev_get_device_list(device_list);
}
#define OFFSET(x) offsetof(FBDevContext, x)
#define DEC AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
@ -227,6 +232,7 @@ AVInputFormat ff_fbdev_demuxer = {
.read_header = fbdev_read_header,
.read_packet = fbdev_read_packet,
.read_close = fbdev_read_close,
.get_device_list = fbdev_get_device_list,
.flags = AVFMT_NOFILE,
.priv_class = &fbdev_class,
};

View File

@ -186,64 +186,7 @@ static av_cold int fbdev_write_trailer(AVFormatContext *h)
static int fbdev_get_device_list(AVFormatContext *s, AVDeviceInfoList *device_list)
{
struct fb_var_screeninfo varinfo;
struct fb_fix_screeninfo fixinfo;
char device_file[12];
AVDeviceInfo *device = NULL;
int i, fd = -1, ret = 0;
const char *default_device = ff_fbdev_default_device();
if (!device_list)
return AVERROR(EINVAL);
for (i = 0; i <= 31; i++) {
snprintf(device_file, sizeof(device_file), "/dev/fb%d", i);
if ((fd = avpriv_open(device_file, O_RDWR)) < 0)
continue;
if (ioctl(fd, FBIOGET_VSCREENINFO, &varinfo) == -1)
goto fail_device;
if (ioctl(fd, FBIOGET_FSCREENINFO, &fixinfo) == -1)
goto fail_device;
device = av_mallocz(sizeof(AVDeviceInfo));
if (!device) {
ret = AVERROR(ENOMEM);
goto fail_device;
}
device->device_name = av_strdup(device_file);
device->device_description = av_strdup(fixinfo.id);
if (!device->device_name || !device->device_description) {
ret = AVERROR(ENOMEM);
goto fail_device;
}
if ((ret = av_dynarray_add_nofree(&device_list->devices,
&device_list->nb_devices, device)) < 0)
goto fail_device;
if (default_device && !strcmp(device->device_name, default_device)) {
device_list->default_device = device_list->nb_devices - 1;
default_device = NULL;
}
close(fd);
fd = -1;
continue;
fail_device:
if (device) {
av_free(device->device_name);
av_free(device->device_description);
av_freep(&device);
}
if (fd >= 0) {
close(fd);
fd = -1;
}
if (ret < 0)
return ret;
}
return 0;
return ff_fbdev_get_device_list(device_list);
}
#define OFFSET(x) offsetof(FBDevContext, x)

View File

@ -38,6 +38,8 @@ typedef struct PulseData {
int64_t timestamp;
int buffer_size; /**< Buffer size in bytes */
int buffer_duration; /**< Buffer size in ms, recalculated to buffer_size */
int prebuf;
int minreq;
int last_result;
pa_threaded_mainloop *mainloop;
pa_context *ctx;
@ -475,6 +477,10 @@ static av_cold int pulse_write_header(AVFormatContext *h)
av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", buffer_attributes.tlength);
} else if (s->buffer_size)
buffer_attributes.tlength = s->buffer_size;
if (s->prebuf)
buffer_attributes.prebuf = s->prebuf;
if (s->minreq)
buffer_attributes.minreq = s->minreq;
sample_spec.format = ff_codec_id_to_pulse_format(st->codec->codec_id);
sample_spec.rate = st->codec->sample_rate;
@ -578,6 +584,14 @@ static av_cold int pulse_write_header(AVFormatContext *h)
goto fail;
}
/* read back buffer attributes for future use */
buffer_attributes = *pa_stream_get_buffer_attr(s->stream);
s->buffer_size = buffer_attributes.tlength;
s->prebuf = buffer_attributes.prebuf;
s->minreq = buffer_attributes.minreq;
av_log(s, AV_LOG_DEBUG, "Real buffer attributes: size: %d, prebuf: %d, minreq: %d\n",
s->buffer_size, s->prebuf, s->minreq);
pa_threaded_mainloop_unlock(s->mainloop);
if ((ret = pulse_subscribe_events(s)) < 0) {
@ -610,6 +624,7 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
{
PulseData *s = h->priv_data;
int ret;
int64_t writable_size;
if (!pkt)
return pulse_flash_stream(s);
@ -632,7 +647,7 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
av_log(s, AV_LOG_ERROR, "PulseAudio stream is in invalid state.\n");
goto fail;
}
while (!pa_stream_writable_size(s->stream)) {
while (pa_stream_writable_size(s->stream) < s->minreq) {
if (s->nonblocking) {
pa_threaded_mainloop_unlock(s->mainloop);
return AVERROR(EAGAIN);
@ -644,6 +659,9 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
av_log(s, AV_LOG_ERROR, "pa_stream_write failed: %s\n", pa_strerror(ret));
goto fail;
}
if ((writable_size = pa_stream_writable_size(s->stream)) >= s->minreq)
avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_WRITABLE, &writable_size, sizeof(writable_size));
pa_threaded_mainloop_unlock(s->mainloop);
return 0;
@ -678,8 +696,10 @@ static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *
pa_threaded_mainloop_lock(s->mainloop);
pa_stream_get_latency(s->stream, &latency, &neg);
pa_threaded_mainloop_unlock(s->mainloop);
*wall = av_gettime();
*dts = s->timestamp - (neg ? -latency : latency);
if (wall)
*wall = av_gettime();
if (dts)
*dts = s->timestamp - (neg ? -latency : latency);
}
static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
@ -745,6 +765,8 @@ static const AVOption options[] = {
{ "device", "set device name", OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ "prebuf", "set pre-buffering size", OFFSET(prebuf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ "minreq", "set minimum request size", OFFSET(minreq), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ NULL }
};