Skip to content
Snippets Groups Projects
Commit 9d277ec9 authored by Julian Rother's avatar Julian Rother
Browse files

Cleanup and restructuring

parent 9a3250d8
Branches
No related tags found
No related merge requests found
......@@ -19,8 +19,10 @@ static char *getxmlattr(xmlAttr *a, char *name, char *err)
char *get_xmpchapters(char *xmp)
{
int i, len, maxlen;
char *out;
int i;
char *ptr;
size_t size;
FILE *stream;
xmlDocPtr doc;
xmlXPathContextPtr xpath;
xmlXPathObjectPtr res;
......@@ -41,51 +43,52 @@ char *get_xmpchapters(char *xmp)
res = xmlXPathEvalExpression("/x:xmpmeta/rdf:RDF/rdf:Description/xmpDM:Tracks/rdf:Bag/rdf:li/rdf:Description/xmpDM:markers/rdf:Seq/rdf:li/rdf:Description", xpath);
if (!res || !res->nodesetval)
return "";
len = 0; maxlen = res->nodesetval->nodeNr*200;
out = malloc(maxlen);
len += xsnprintf(out+len, maxlen-len-1, "[");
ptr = 0;
size = 0;
if (!(stream = open_memstream(&ptr, &size)))
exit(99);
fprintf(stream, "[");
for (i = 0; i < res->nodesetval->nodeNr; i ++)
{
start = atoi(getxmlattr(res->nodesetval->nodeTab[i]->properties, "startTime", "0"))/framerate;
if (i)
len += xsnprintf(out+len, maxlen-len-1, ",");
len += xsnprintf(out+len, maxlen-len-1, "{\"time\": %f, \"text\": \"%s\"}",
start, jescape(getxmlattr(res->nodesetval->nodeTab[i]->properties, "name", "")));
fprintf(stream, ",");
fprintf(stream, "{\"time\": %f, \"text\": \"%s\"}", start,
jescape(getxmlattr(res->nodesetval->nodeTab[i]->properties, "name", "")));
}
len += xsnprintf(out+len, maxlen-len-1, "]");
return out;
fprintf(stream, "]");
fclose(stream);
return ptr;
}
int main(int argc, char *argv[])
{
int jobid;
char path[100], *xmp;
int err;
char *path, *xmp;
AVFormatContext *demux, *mux;
AVDictionaryEntry *tag;
AVDictionary *opts;
if (argc != 5)
return 1;
av_register_all();
av_log_set_callback(avlogbuf_callback);
init_avlogbuf();
jobid = atoi(argv[1]);
xsnprintf(BL(path), "%s/%s", CONFIG_VIDEOS_RAW,
jstr(jlookup(argv[4], "path"), ""));
path = mprintf("%s/%s", CONFIG_VIDEOS_RAW, jstr(jlookup(argv[4], "path"), ""));
ping_job(jobid, "running", 0);
opts = 0;
av_dict_set_int(&opts, "export_xmp", 1, 0);
demux = 0;
if (avformat_open_input(&demux, path, 0, &opts))
goto fail;
if (err = avformat_open_input(&demux, path, 0, &opts))
job_failed("Opening input file failed: %s", av_err2str(err));
avformat_find_stream_info(demux, 0);
if (tag = av_dict_get(demux->metadata, "xmp", 0, 0))
ping_job(jobid, "finished", "{\"xmp_chapters\": %s, \"duration\": %f, \"log\": \"%s\"}", get_xmpchapters(tag->value), demux->duration*av_q2d(AV_TIME_BASE_Q), get_avlogbuf());
ping_job(jobid, "finished", "{\"xmp_chapters\": %s, \"duration\": %f, \"log\": \"%s\"}",
get_xmpchapters(tag->value), demux->duration*av_q2d(AV_TIME_BASE_Q),
jescape(get_avlogbuf()));
else
ping_job(jobid, "finished", "{\"duration\": %f, \"log\": \"%s\"}", demux->duration*av_q2d(AV_TIME_BASE_Q), get_avlogbuf());
ping_job(jobid, "finished", "{\"duration\": %f, \"log\": \"%s\"}",
demux->duration*av_q2d(AV_TIME_BASE_Q), jescape(get_avlogbuf()));
return 0;
fail:
ping_job(jobid, "failed", "{\"log\": \"%s\"}", get_avlogbuf());
return 1;
}
......@@ -42,9 +42,9 @@ void parse_chapters(AVFormatContext *ctx, char *s, int duration)
int main(int argc, char *argv[])
{
int jobid, i;
int i, err;
int *idxmap;
char *p, path[100], tmp[100];
char *p, *path, *tmp;
AVFormatContext *demux, *mux;
AVPacket pkt;
AVStream *stream;
......@@ -52,19 +52,18 @@ int main(int argc, char *argv[])
if (argc != 5)
return 1;
av_register_all();
av_log_set_callback(avlogbuf_callback);
init_avlogbuf();
memset(&pkt, 0, sizeof(pkt));
av_init_packet(&pkt);
jobid = atoi(argv[1]);
xsnprintf(BL(path), "%s/%s", CONFIG_VIDEOS_RELEASED,
jstr(jlookup(argv[4], "path"), ""));
xsnprintf(BL(tmp), "%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
path = mprintf("%s/%s", CONFIG_VIDEOS_RELEASED, jstr(jlookup(argv[4], "path"), ""));
tmp = mprintf("%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
ping_job(jobid, "running", 0);
demux = 0;
if (avformat_open_input(&demux, path, 0, 0))
goto fail;
if (err = avformat_open_input(&demux, path, 0, 0))
job_failed("Opening input file failed: %s", av_err2str(err));
avformat_find_stream_info(demux, 0);
avformat_alloc_output_context2(&mux, 0, jstr(jlookup(argv[4], "format"), 0), path);
av_dict_copy(&mux->metadata, demux->metadata, 0);
......@@ -89,8 +88,8 @@ int main(int argc, char *argv[])
avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE);
muxopts = 0;
parse_dict(&muxopts, jlookup(argv[4], "options"));
if (avformat_write_header(mux, &muxopts) < 0)
goto fail;
if ((err = avformat_write_header(mux, &muxopts)) < 0)
job_failed("Writing temporary file failed: %s", av_err2str(err));
while (!av_read_frame(demux, &pkt))
{
if (pkt.stream_index >= demux->nb_streams
......@@ -104,21 +103,16 @@ int main(int argc, char *argv[])
pkt.duration = av_rescale_q(pkt.duration, demux->streams[pkt.stream_index]->time_base,
mux->streams[pkt.stream_index]->time_base);
pkt.pos = -1;
if (av_interleaved_write_frame(mux, &pkt))
goto fail;
if (err = av_interleaved_write_frame(mux, &pkt))
job_failed("Could not write frame: %s", av_err2str(err));
}
av_interleaved_write_frame(mux, 0);
if (av_write_trailer(mux))
goto fail;
if (err = av_write_trailer(mux))
job_failed("Error writing trailer to temporary file", av_err2str(err));
avio_closep(&mux->pb);
if (rename(tmp, path))
goto fail;
job_failed("Overwriting output file failed: %s", strerror(errno));
unlink(tmp);
ping_job(jobid, "finished", "{\"log\": \"%s\"}", get_avlogbuf());
ping_job(jobid, "finished", "{\"log\": \"%s\"}", jescape(get_avlogbuf()));
return 0;
fail:
unlink(tmp);
ping_job(jobid, "failed", "{\"log\": \"%s\"}", get_avlogbuf());
return 1;
}
......@@ -24,8 +24,8 @@ AVFrame *scale_frame(AVFrame *frame, enum AVPixelFormat pix_fmt,
int main(int argc, char *argv[])
{
int jobid, vidx;
char lectureid[JSTR_SIZE], src[100], tmp[100], dest[100];
int err, vidx;
char lectureid[JSTR_SIZE], *src, *tmp, *dest;
AVFormatContext *demux, *mux;
AVCodecContext *dec, *enc;
AVPacket pkt;
......@@ -33,25 +33,23 @@ int main(int argc, char *argv[])
if (argc != 5)
return 1;
av_register_all();
av_log_set_callback(avlogbuf_callback);
init_avlogbuf();
/* Prepare arguments */
jobid = atoi(argv[1]);
jstrb(jlookup(argv[4], "lectureid"), "-1", lectureid);
xsnprintf(BL(src), "%s/%s", CONFIG_VIDEOS_RELEASED,
jstr(jlookup(argv[4], "path"), ""));
xsnprintf(BL(tmp), "%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
xsnprintf(BL(dest), "%s/thumbnail/l_%s.jpg", CONFIG_VIDEOS_RELEASED,
lectureid);
src = mprintf("%s/%s", CONFIG_VIDEOS_RELEASED, jstr(jlookup(argv[4], "path"), ""));
tmp = mprintf("%s/.tmp-%i", CONFIG_VIDEOS_TMP, jobid);
dest = mprintf("%s/thumbnail/l_%s.jpg", CONFIG_VIDEOS_RELEASED, lectureid);
ping_job(jobid, "running", 0);
/* Open src */
demux = 0;
if (avformat_open_input(&demux, src, 0, 0))
goto fail;
if (err = avformat_open_input(&demux, src, 0, 0))
job_failed("Opening input file failed: %s", av_err2str(err));
avformat_find_stream_info(demux, 0);
if ((vidx = av_find_best_stream(demux, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0)) < 0)
goto fail;
job_failed("Could not find video stream in input file");
dec = avcodec_alloc_context3(avcodec_find_decoder(demux->streams[vidx]->codecpar->codec_id));
avcodec_parameters_to_context(dec, demux->streams[vidx]->codecpar);
avcodec_open2(dec, dec->codec, 0);
......@@ -71,8 +69,8 @@ int main(int argc, char *argv[])
avio_open(&mux->pb, tmp, AVIO_FLAG_WRITE);
avcodec_open2(enc, enc->codec, 0);
avcodec_parameters_from_context(mux->streams[0]->codecpar, enc);
if (avformat_write_header(mux, 0) < 0)
goto fail;
if ((err = avformat_write_header(mux, 0)) < 0)
job_failed("Writing temporary file failed: %s", av_err2str(err));
/* Create thumbnail */
av_seek_frame(demux, -1, (2L*demux->duration)/5L, 0);
......@@ -81,8 +79,8 @@ int main(int argc, char *argv[])
frame = av_frame_alloc();
do
{
if (av_read_frame(demux, &pkt))
goto fail;
if (err = av_read_frame(demux, &pkt))
job_failed("Reading frame failed: %s", av_err2str(err));
if (pkt.stream_index == vidx)
avcodec_send_packet(dec, &pkt);
}
......@@ -97,17 +95,12 @@ int main(int argc, char *argv[])
av_interleaved_write_frame(mux, &pkt);
}
av_interleaved_write_frame(mux, 0);
if (av_write_trailer(mux))
goto fail;
if (err = av_write_trailer(mux))
job_failed("Error writing trailer to temporary file: %s", av_err2str(err));
avio_closep(&mux->pb);
if (rename(tmp, dest))
goto fail;
job_failed("Overwriting output file failed: %s", strerror(errno));
unlink(tmp);
ping_job(jobid, "finished", "{\"log\": \"%s\"}", get_avlogbuf());
ping_job(jobid, "finished", "{\"log\": \"%s\"}", jescape(get_avlogbuf()));
return 0;
fail:
unlink(tmp);
ping_job(jobid, "failed", "{\"log\": \"%s\"}", get_avlogbuf());
return 1;
}
......@@ -4,14 +4,19 @@
/* Generic */
#define SL(s) (s), (sizeof(s)-1)
#define BL(b) (b), (sizeof(b))
size_t xvsnprintf(char *p, size_t len, const char *fmt, va_list ap);
size_t xsnprintf(char *p, size_t len, const char *fmt, ...);
extern int jobid;
char *vmprintf(const char *fmt, va_list ap);
char *mprintf(const char *fmt, ...);
/* Logging */
void init_avlogbuf(void);
void avlogbuf_callback(void *classp, int level, const char *fmt, va_list ap);
char *get_avlogbuf(void);
/* API */
int ping_job(int id, char *state, char *status, ...);
void job_failed(char *msg, ...);
/* JSON parser */
#define JSTR_SIZE 100
......@@ -24,4 +29,6 @@ char *jenter(char *s);
char *jnext(char *s);
char *jvalue(char *s);
char *jlookup(char *s, char *key);
/* JSON util */
char *jescape(char *s);
#include <curl/curl.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
......@@ -9,7 +10,7 @@
static size_t curl_write_cb(char *ptr, size_t size, size_t nmemb, void *user)
{
return size;
return size*nmemb;
}
int ping_job(int id, char *state, char *status, ...)
......@@ -17,39 +18,44 @@ int ping_job(int id, char *state, char *status, ...)
int ret;
CURL *curl;
va_list ap;
char *e_host, *e_status, *e_apikey, *e_state;
char url[100], buf[500];
char *p, *url, *e_host, *e_status, *e_apikey, *e_state;
char hostbuf[HOST_NAME_MAX+1];
if (!(curl = curl_easy_init()))
return -1;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
e_apikey = curl_easy_escape(curl, CONFIG_APIKEY, 0);
e_state = curl_easy_escape(curl, state, 0);
if (gethostname(BL(buf)))
strcpy(buf, "localhost");
buf[sizeof(buf)-1] = 0;
e_host = curl_easy_escape(curl, buf, 0);
if (gethostname(BL(hostbuf)))
strcpy(hostbuf, "localhost");
e_host = curl_easy_escape(curl, hostbuf, 0);
if (status)
{
va_start(ap, status);
xvsnprintf(BL(buf), status, ap);
p = vmprintf(status, ap);
va_end(ap);
}
else
strcpy(buf, "{}");
e_status = curl_easy_escape(curl, buf, 0);
xsnprintf(BL(buf), "apikey=%s&state=%s&host=%s&status=%s",
e_apikey, e_state, e_host, e_status);
p = strdup("{}");
e_status = curl_easy_escape(curl, p, 0);
free(p);
p = mprintf("apikey=%s&state=%s&host=%s&status=%s", e_apikey, e_state,
e_host, e_status);
curl_free(e_apikey);
curl_free(e_state);
curl_free(e_host);
curl_free(e_status);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf);
xsnprintf(BL(url), "%s/internal/jobs/api/job/%i/ping", CONFIG_APIBASE, id);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, p);
url = mprintf("%s/internal/jobs/api/job/%i/ping", CONFIG_APIBASE, id);
curl_easy_setopt(curl, CURLOPT_URL, url);
ret = curl_easy_perform(curl);
free(p);
free(url);
curl_easy_cleanup(curl);
if (ret)
{
fprintf(stderr, "API call to \"%s\" failed: %s\n", url, curl_easy_strerror(ret));
return -1;
}
else
return 0;
}
......@@ -3,41 +3,38 @@
#include "../util.h"
static char *logbuffer = 0;
static size_t logoffset = 0, logsize = 0;
static pthread_mutex_t loglock = PTHREAD_MUTEX_INITIALIZER;;
static char *logbuffer;
static size_t logsize;
static FILE *logstream;
void init_avlogbuf(void)
{
logbuffer = 0;
logsize = 0;
if (!(logstream = open_memstream(&logbuffer, &logsize)))
exit(99);
av_log_set_callback(avlogbuf_callback);
}
void avlogbuf_callback(void *class, int level, const char *fmt, va_list ap)
{
int len, print_prefix;
int print_prefix;
char buf[200];
if (level >= AV_LOG_VERBOSE)
return;
av_log_default_callback(class, level, fmt, ap);
if (pthread_mutex_lock(&loglock))
return;
if (logsize-logoffset < 1024)
logbuffer = realloc(logbuffer, (logsize += 1024));
if (!logbuffer)
return;
print_prefix = 1;
len = av_log_format_line2(class, level, fmt, ap, logbuffer+logoffset,
logsize-logoffset, &print_prefix);
if (len < logsize-logoffset)
logoffset += len;
else
logoffset = logsize-1;
pthread_mutex_unlock(&loglock);
av_log_format_line(class, level, fmt, ap, BL(buf), &print_prefix);
fputs(buf, logstream);
}
char *get_avlogbuf(void)
{
char *ret, *p;
if (!logbuffer || pthread_mutex_lock(&loglock))
return strdup("");
ret = strdup(logbuffer);
pthread_mutex_unlock(&loglock);
for (p = ret; *p; p ++)
if (*p == '"')
*p = '\'';
return ret;
char *p;
if (!logstream)
return "";
fclose(logstream);
p = logbuffer;
init_avlogbuf();
fputs(p, logstream);
return p;
}
#include <stdio.h>
#include <stdlib.h>
#include "../util.h"
char *jescape(char *s)
{
int i;
char *ptr;
size_t size;
FILE *stream;
if (!(stream = open_memstream(&ptr, &size)))
exit(99);
for (; *s; s ++)
switch (*s)
{
case '"':
fputs("\\\"", stream); break;
case '\\':
fputs("\\\\", stream); break;
case '\b':
fputs("\\b", stream); break;
case '\f':
fputs("\\f", stream); break;
case '\n':
fputs("\\n", stream); break;
case '\r':
fputs("\\r", stream); break;
case '\t':
fputs("\\t", stream); break;
default:
if (*s <= 0x1f)
fprintf(stream, "\\u%04x", *s);
else
fputc(*s, stream);
}
fclose(stream);
return ptr;
}
#include <stdio.h>
#include <stdlib.h>
#include "../util.h"
int jobid;
void job_failed(char *msg, ...)
{
va_list ap;
va_start(ap, msg);
ping_job(jobid, "failed", "{\"reason\": \"%s\", \"log\": \"%s\"}",
jescape(vmprintf(msg, ap)), jescape(get_avlogbuf()));
va_end(ap);
exit(2);
}
......@@ -5,9 +5,6 @@
#include "../util.h"
static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};
static char *skip_ws(char *s)
{
for (; *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'; s ++);
......@@ -213,41 +210,3 @@ char *jlookup(char *s, char *key)
return jvalue(s);
return 0;
}
char *jescape(char *s)
{
int i;
static __thread char buf[JSTR_SIZE];
for (i = 0; *s && i+7 < sizeof(buf); s ++)
switch (*s)
{
case '"':
buf[i ++] = '\\'; buf[i ++] = '"'; break;
case '\\':
buf[i ++] = '\\'; buf[i ++] = '\\'; break;
case '\b':
buf[i ++] = '\\'; buf[i ++] = 'b'; break;
case '\f':
buf[i ++] = '\\'; buf[i ++] = 'f'; break;
case '\n':
buf[i ++] = '\\'; buf[i ++] = 'n'; break;
case '\r':
buf[i ++] = '\\'; buf[i ++] = 'r'; break;
case '\t':
buf[i ++] = '\\'; buf[i ++] = 't'; break;
default:
if (*s <= 0x1f)
{
buf[i ++] = '\\';
buf[i ++] = 'u';
buf[i ++] = '0';
buf[i ++] = '0';
buf[i ++] = hex[*s >> 4];
buf[i ++] = hex[*s & 0xf];
}
else
buf[i ++] = *s;
}
buf[i] = 0;
return buf;
}
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "../util.h"
char *vmprintf(const char *fmt, va_list ap)
{
char *ptr;
size_t size;
FILE *stream;
ptr = 0;
size = 0;
if (!(stream = open_memstream(&ptr, &size)))
exit(99);
if (vfprintf(stream, fmt, ap) < 0)
exit(99);
fclose(stream);
return ptr;
}
char *mprintf(const char *fmt, ...)
{
char *ret;
va_list ap;
va_start(ap, fmt);
ret = vmprintf(fmt, ap);
va_end(ap);
return ret;
}
#include <stdio.h>
#include <stdarg.h>
#include "../util.h"
size_t xvsnprintf(char *p, size_t len, const char *fmt, va_list ap)
{
int ret;
if ((ret = vsnprintf(p, len, fmt, ap)) >= len)
{
p[len-1] = 0;
return len;
}
return ret;
}
size_t xsnprintf(char *p, size_t len, const char *fmt, ...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(p, len, fmt, ap);
va_end(ap);
return ret;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment