probe.c 2.76 KB
Newer Older
Julian Rother's avatar
Julian Rother committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#include "util.h"
#include "config.h"

static char *getxmlattr(xmlAttr *a, char *name, char *err)
{
	for (; a && strcmp(a->name, name); a = a->next);
	if (!a)
		return err;
	return a->children->content;
}

char *get_xmpchapters(char *xmp)
{
Julian Rother's avatar
Julian Rother committed
22
23
24
25
	int i;
	char *ptr;
	size_t size;
	FILE *stream;
Julian Rother's avatar
Julian Rother committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
	xmlDocPtr doc;
	xmlXPathContextPtr xpath;
	xmlXPathObjectPtr res;
	xmlNodePtr node;
	double framerate, start;
	if (!(doc = xmlParseMemory(xmp, strlen(xmp))))
		return "";
	if (!(xpath = xmlXPathNewContext(doc)))
		return "";
	xmlXPathRegisterNs(xpath, "x", "adobe:ns:meta/");
	xmlXPathRegisterNs(xpath, "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
	xmlXPathRegisterNs(xpath, "xmpDM", "http://ns.adobe.com/xmp/1.0/DynamicMedia/");
	res = xmlXPathEvalExpression("/x:xmpmeta/rdf:RDF/rdf:Description/@xmpDM:videoFrameRate", xpath);
	if (!res || !res->nodesetval->nodeNr)
		return "";
	framerate = strtod(res->nodesetval->nodeTab[0]->children->content, 0);
	xmlXPathFreeObject(res);
	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 "";
Julian Rother's avatar
Julian Rother committed
46
47
48
49
50
	ptr = 0;
	size = 0;
	if (!(stream = open_memstream(&ptr, &size)))
		exit(99);
	fprintf(stream, "[");
Julian Rother's avatar
Julian Rother committed
51
52
53
54
	for (i = 0; i < res->nodesetval->nodeNr; i ++)
	{
		start = atoi(getxmlattr(res->nodesetval->nodeTab[i]->properties, "startTime", "0"))/framerate;
		if (i)
Julian Rother's avatar
Julian Rother committed
55
56
57
			fprintf(stream, ",");
		fprintf(stream, "{\"time\": %f, \"text\": \"%s\"}", start,
				jescape(getxmlattr(res->nodesetval->nodeTab[i]->properties, "name", "")));
Julian Rother's avatar
Julian Rother committed
58
	}
Julian Rother's avatar
Julian Rother committed
59
60
61
	fprintf(stream, "]");
	fclose(stream);
	return ptr;
Julian Rother's avatar
Julian Rother committed
62
63
64
65
}

int main(int argc, char *argv[])
{
Julian Rother's avatar
Julian Rother committed
66
67
	int err;
	char *path, *xmp;
Julian Rother's avatar
Julian Rother committed
68
69
70
71
72
73
	AVFormatContext *demux, *mux;
	AVDictionaryEntry *tag;
	AVDictionary *opts;
	if (argc != 5)
		return 1;
	av_register_all();
Julian Rother's avatar
Julian Rother committed
74
	init_avlogbuf();
Julian Rother's avatar
Julian Rother committed
75
76

	jobid = atoi(argv[1]);
Julian Rother's avatar
Julian Rother committed
77
	path = mprintf("%s/%s", CONFIG_VIDEOS_RAW, jstr(jlookup(argv[4], "path"), ""));
Julian Rother's avatar
Julian Rother committed
78
79
80
81
82
	ping_job(jobid, "running", 0);

	opts = 0;
	av_dict_set_int(&opts, "export_xmp", 1, 0);
	demux = 0;
Julian Rother's avatar
Julian Rother committed
83
84
	if (err = avformat_open_input(&demux, path, 0, &opts))
		job_failed("Opening input file failed: %s", av_err2str(err));
Julian Rother's avatar
Julian Rother committed
85
86
	avformat_find_stream_info(demux, 0);
	if (tag = av_dict_get(demux->metadata, "xmp", 0, 0))
Julian Rother's avatar
Julian Rother committed
87
88
89
		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()));
Julian Rother's avatar
Julian Rother committed
90
	else
Julian Rother's avatar
Julian Rother committed
91
92
		ping_job(jobid, "finished", "{\"duration\": %f, \"log\": \"%s\"}",
				demux->duration*av_q2d(AV_TIME_BASE_Q), jescape(get_avlogbuf()));
Julian Rother's avatar
Julian Rother committed
93
94
	return 0;
}