Imported Upstream version 0.14.2+dfsg1

This commit is contained in:
Sebastian Ramacher 2016-05-24 21:53:01 +02:00
parent fb3990e9e5
commit 41a01dbf05
529 changed files with 25112 additions and 2336 deletions

View file

@ -29,6 +29,9 @@ struct update_info {
obs_data_t *cache_package;
obs_data_t *remote_package;
char *etag_local;
char *etag_remote;
confirm_file_callback_t callback;
void *param;
@ -76,7 +79,33 @@ static size_t http_write(uint8_t *ptr, size_t size, size_t nmemb,
return total;
}
static bool do_http_request(struct update_info *info, const char *url)
static size_t http_header(char *buffer, size_t size, size_t nitems,
struct update_info *info)
{
if (!strncmp(buffer, "ETag: ", 6))
{
char *etag = buffer + 6;
if (*etag) {
char *etag_clean, *p;
etag_clean = bstrdup(etag);
p = strchr(etag_clean, '\r');
if (p)
*p = 0;
p = strchr(etag_clean, '\n');
if (p)
*p = 0;
info->etag_remote = etag_clean;
}
}
return nitems * size;
}
static bool do_http_request(struct update_info *info, const char *url,
long *response_code)
{
CURLcode code;
uint8_t null_terminator = 0;
@ -89,6 +118,17 @@ static bool do_http_request(struct update_info *info, const char *url)
curl_easy_setopt(info->curl, CURLOPT_WRITEDATA, info);
curl_easy_setopt(info->curl, CURLOPT_FAILONERROR, true);
if (!info->remote_url) {
// We only care about headers from the main package file
curl_easy_setopt(info->curl, CURLOPT_HEADERFUNCTION, http_header);
curl_easy_setopt(info->curl, CURLOPT_HEADERDATA, info);
}
#if LIBCURL_VERSION_NUM >= 0x072400
// A lot of servers don't yet support ALPN
curl_easy_setopt(info->curl, CURLOPT_SSL_ENABLE_ALPN, 0);
#endif
code = curl_easy_perform(info->curl);
if (code != CURLE_OK) {
warn("Remote update of URL \"%s\" failed: %s", url,
@ -96,6 +136,16 @@ static bool do_http_request(struct update_info *info, const char *url)
return false;
}
if (curl_easy_getinfo(info->curl, CURLINFO_RESPONSE_CODE,
response_code) != CURLE_OK)
return false;
if (*response_code >= 400) {
warn("Remote update of URL \"%s\" failed: HTTP/%ld", url,
*response_code);
return false;
}
da_push_back(info->file_data, &null_terminator);
return true;
@ -135,6 +185,25 @@ static bool init_update(struct update_info *info)
info->local_package = get_package(info->local, "package.json");
info->cache_package = get_package(info->cache, "package.json");
obs_data_t *metadata = get_package(info->cache, "meta.json");
if (metadata) {
const char *etag = obs_data_get_string(metadata, "etag");
if (etag) {
struct dstr if_none_match = { 0 };
dstr_copy(&if_none_match, "If-None-Match: ");
dstr_cat(&if_none_match, etag);
info->etag_local = bstrdup(etag);
info->header = curl_slist_append(info->header,
if_none_match.array);
dstr_free(&if_none_match);
}
obs_data_release(metadata);
}
dstr_copy(&user_agent, "User-Agent: ");
dstr_cat(&user_agent, info->user_agent);
@ -246,10 +315,11 @@ static int update_local_version(struct update_info *info)
static inline bool do_relative_http_request(struct update_info *info,
const char *url, const char *file)
{
long response_code;
char *full_url = get_path(url, file);
bool success = do_http_request(info, full_url);
bool success = do_http_request(info, full_url, &response_code);
bfree(full_url);
return success;
return success && response_code == 200;
}
static inline void write_file_data(struct update_info *info,
@ -320,11 +390,34 @@ static bool update_remote_files(void *param, obs_data_t *remote_file)
return true;
}
static void update_save_metadata(struct update_info *info)
{
struct dstr path = { 0 };
if (!info->etag_remote)
return;
dstr_copy(&path, info->cache);
dstr_cat(&path, "meta.json");
obs_data_t *data;
data = obs_data_create();
obs_data_set_string(data, "etag", info->etag_remote);
obs_data_save_json(data, path.array);
obs_data_release(data);
dstr_free(&path);
}
static void update_remote_version(struct update_info *info, int cur_version)
{
int remote_version;
long response_code;
if (!do_http_request(info, info->url))
if (!do_http_request(info, info->url, &response_code))
return;
if (response_code == 304)
return;
if (!info->file_data.array || info->file_data.array[0] != '{') {
@ -332,6 +425,8 @@ static void update_remote_version(struct update_info *info, int cur_version)
return;
}
update_save_metadata(info);
info->remote_package = obs_data_create_from_json(
(char*)info->file_data.array);
if (!info->remote_package) {
@ -371,6 +466,12 @@ static void *update_thread(void *data)
cur_version = update_local_version(info);
update_remote_version(info, cur_version);
os_rmdir(info->temp);
if (info->etag_local)
bfree(info->etag_local);
if (info->etag_remote)
bfree(info->etag_remote);
return NULL;
}

View file

@ -28,6 +28,8 @@
#include <assert.h>
#include "ff-compat.h"
static inline void shrink_packet(struct ff_packet *packet, int packet_length)
{
if (packet_length <= packet->base.size) {
@ -47,11 +49,6 @@ static bool handle_reset_packet(struct ff_decoder *decoder,
decoder->clock = packet->clock;
av_free_packet(&packet->base);
// not a real packet, so try to get another packet
if (packet_queue_get(&decoder->packet_queue, packet, 1)
== FF_PACKET_FAIL)
return false;
return true;
}
@ -73,6 +70,28 @@ static int decode_frame(struct ff_decoder *decoder,
int ret;
while (true) {
if (decoder->eof)
ret = packet_queue_get(&decoder->packet_queue, packet, 0);
else
ret = packet_queue_get(&decoder->packet_queue, packet, 1);
if (ret == FF_PACKET_EMPTY) {
return 0;
} else if (ret == FF_PACKET_FAIL) {
return -1;
}
if (packet->base.data ==
decoder->packet_queue.flush_packet.base.data) {
avcodec_flush_buffers(decoder->codec);
continue;
}
// Packet has a new clock (reset packet)
if (packet->clock != NULL)
if (!handle_reset_packet(decoder, packet))
return -1;
while (packet->base.size > 0) {
int complete;
@ -93,33 +112,11 @@ static int decode_frame(struct ff_decoder *decoder,
*frame_complete = complete != 0;
return frame->nb_samples *
av_get_bytes_per_sample(frame->format);
av_get_bytes_per_sample(frame->format);
}
if (packet->base.data != NULL)
av_packet_unref(&packet->base);
ret = packet_queue_get(&decoder->packet_queue, packet, 1);
if (ret == FF_PACKET_FAIL) {
return -1;
}
if (packet->base.data ==
decoder->packet_queue.flush_packet.base.data) {
avcodec_flush_buffers(decoder->codec);
// we were flushed, so try to get another packet
ret = packet_queue_get(&decoder->packet_queue,
packet, 1);
if (ret == FF_PACKET_FAIL) {
return -1;
}
}
// Packet has a new clock (reset packet)
if (packet->clock != NULL)
if (!handle_reset_packet(decoder, packet))
return -1;
}
}
@ -143,8 +140,10 @@ static bool queue_frame(struct ff_decoder *decoder, AVFrame *frame,
|| queue_frame->frame->sample_rate != codec->sample_rate
|| queue_frame->frame->format != codec->sample_fmt);
if (queue_frame->frame != NULL)
if (queue_frame->frame != NULL) {
//FIXME: this shouldn't happen any more!
av_frame_free(&queue_frame->frame);
}
queue_frame->frame = av_frame_clone(frame);
queue_frame->clock = ff_clock_retain(decoder->clock);
@ -166,10 +165,13 @@ void *ff_audio_decoder_thread(void *opaque_audio_decoder)
struct ff_packet packet = {0};
bool frame_complete;
AVFrame *frame = av_frame_alloc();
int ret;
while (!decoder->abort) {
if (decode_frame(decoder, &packet, frame, &frame_complete)
< 0) {
ret = decode_frame(decoder, &packet, frame, &frame_complete);
if (ret == 0) {
break;
} else if (ret < 0) {
av_free_packet(&packet.base);
continue;
}
@ -193,5 +195,8 @@ void *ff_audio_decoder_thread(void *opaque_audio_decoder)
ff_clock_release(&decoder->clock);
av_frame_free(&frame);
decoder->finished = true;
return NULL;
}

29
deps/libff/libff/ff-compat.h vendored Normal file
View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2016 Hugh Bailey <obs.jim@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#if LIBAVCODEC_VERSION_MAJOR >= 57
#define av_free_packet av_packet_unref
static inline int av_dup_packet_2(AVPacket *pkt)
{
AVPacket tmp = *pkt;
int ret = av_packet_ref(pkt, &tmp);
av_packet_unref(&tmp);
return ret;
}
#define av_dup_packet av_dup_packet_2
#endif

View file

@ -42,6 +42,7 @@ struct ff_decoder *ff_decoder_init(AVCodecContext *codec_context,
decoder->codec->opaque = decoder;
decoder->stream = stream;
decoder->abort = false;
decoder->finished = false;
decoder->packet_queue_size = packet_queue_size;
if (!packet_queue_init(&decoder->packet_queue))
@ -179,7 +180,7 @@ void ff_decoder_refresh(void *opaque)
if (decoder && decoder->stream) {
if (decoder->frame_queue.size == 0) {
if (!decoder->eof) {
if (!decoder->eof || !decoder->finished) {
// We expected a frame, but there were none
// available
@ -280,6 +281,8 @@ void ff_decoder_refresh(void *opaque)
(int)(delay_until_next_wake * 1000
+ 0.5L));
av_frame_free(&frame->frame);
ff_circular_queue_advance_read(&decoder->frame_queue);
}
} else {

View file

@ -56,6 +56,7 @@ struct ff_decoder {
bool first_frame;
bool eof;
bool abort;
bool finished;
};
typedef struct ff_decoder ff_decoder_t;

View file

@ -23,6 +23,8 @@
#include <assert.h>
#include "ff-compat.h"
#define DEFAULT_AV_SYNC_TYPE AV_SYNC_VIDEO_MASTER
#define AUDIO_FRAME_QUEUE_SIZE 1
@ -92,7 +94,7 @@ void ff_demuxer_free(struct ff_demuxer *demuxer)
ff_decoder_free(demuxer->video_decoder);
if (demuxer->format_context)
avformat_free_context(demuxer->format_context);
avformat_close_input(&demuxer->format_context);
av_free(demuxer);
}
@ -342,15 +344,15 @@ void ff_demuxer_reset(struct ff_demuxer *demuxer)
packet.clock = clock;
if (demuxer->audio_decoder != NULL) {
ff_clock_retain(clock);
packet_queue_put(&demuxer->audio_decoder->packet_queue,
&packet);
ff_clock_retain(clock);
}
if (demuxer->video_decoder != NULL) {
ff_clock_retain(clock);
packet_queue_put(&demuxer->video_decoder->packet_queue,
&packet);
ff_clock_retain(clock);
}
}
@ -500,7 +502,7 @@ static bool handle_seek(struct ff_demuxer *demuxer)
seek_stream = demuxer->audio_decoder->stream;
}
if (seek_stream != NULL) {
if (seek_stream != NULL && demuxer->format_context->duration != AV_NOPTS_VALUE) {
seek_target = av_rescale_q(seek_target,
AV_TIME_BASE_Q,
seek_stream->time_base);
@ -529,8 +531,13 @@ static bool handle_seek(struct ff_demuxer *demuxer)
static void seek_beginning(struct ff_demuxer *demuxer)
{
demuxer->seek_flags = AVSEEK_FLAG_BACKWARD;
demuxer->seek_pos = demuxer->format_context->start_time;
if (demuxer->format_context->duration == AV_NOPTS_VALUE) {
demuxer->seek_flags = AVSEEK_FLAG_FRAME;
demuxer->seek_pos = 0;
} else {
demuxer->seek_flags = AVSEEK_FLAG_BACKWARD;
demuxer->seek_pos = demuxer->format_context->start_time;
}
demuxer->seek_request = true;
demuxer->seek_flush = false;
av_log(NULL, AV_LOG_VERBOSE, "looping media %s", demuxer->input);

View file

@ -15,6 +15,7 @@
*/
#include "ff-packet-queue.h"
#include "ff-compat.h"
bool packet_queue_init(struct ff_packet_queue *q)
{
@ -60,10 +61,6 @@ int packet_queue_put(struct ff_packet_queue *q, struct ff_packet *packet)
{
struct ff_packet_list *new_packet;
if (packet != &q->flush_packet
&& av_dup_packet(&packet->base) < 0)
return FF_PACKET_FAIL;
new_packet = av_malloc(sizeof(struct ff_packet_list));
if (new_packet == NULL)

View file

@ -51,6 +51,9 @@ static void *timer_thread(void *opaque)
- current_time));
}
pthread_mutex_unlock(&timer->mutex);
continue;
// we can be woken up merely to set a sooner wake time
} else {

View file

@ -27,6 +27,8 @@
#include <assert.h>
#include "ff-compat.h"
static bool queue_frame(struct ff_decoder *decoder, AVFrame *frame,
double best_effort_pts)
{
@ -49,8 +51,11 @@ static bool queue_frame(struct ff_decoder *decoder, AVFrame *frame,
|| queue_frame->frame->height != codec->height
|| queue_frame->frame->format != codec->pix_fmt);
if (queue_frame->frame != NULL)
if (queue_frame->frame != NULL) {
// This shouldn't happen any more, the frames are freed in
// ff_decoder_refresh.
av_frame_free(&queue_frame->frame);
}
queue_frame->frame = av_frame_clone(frame);
queue_frame->clock = ff_clock_retain(decoder->clock);
@ -76,8 +81,12 @@ void *ff_video_decoder_thread(void *opaque_video_decoder)
bool key_frame;
while (!decoder->abort) {
ret = packet_queue_get(&decoder->packet_queue, &packet, 1);
if (ret == FF_PACKET_FAIL) {
if (decoder->eof)
ret = packet_queue_get(&decoder->packet_queue, &packet, 0);
else
ret = packet_queue_get(&decoder->packet_queue, &packet, 1);
if (ret == FF_PACKET_EMPTY || ret == FF_PACKET_FAIL) {
// should we just use abort here?
break;
}
@ -135,5 +144,8 @@ void *ff_video_decoder_thread(void *opaque_video_decoder)
ff_clock_release(&decoder->clock);
av_frame_free(&frame);
decoder->finished = true;
return NULL;
}