1 /*
2    Copyright (C) 2008 Annodex Association
3 
4    Based on anx_time.c from libannodex, Copyright (C) 2003 Commonwealth
5    Scientific and Industrial Research Organisation (CSIRO) Australia
6 
7    Redistribution and use in source and binary forms, with or without
8    modification, are permitted provided that the following conditions
9    are met:
10 
11    - Redistributions of source code must retain the above copyright
12    notice, this list of conditions and the following disclaimer.
13 
14    - Redistributions in binary form must reproduce the above copyright
15    notice, this list of conditions and the following disclaimer in the
16    documentation and/or other materials provided with the distribution.
17 
18    - Neither the name of CSIRO Australia nor the names of its
19    contributors may be used to endorse or promote products derived from
20    this software without specific prior written permission.
21 
22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
26    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #include "config.h"
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <math.h>
41 
42 static double
parse_npt(const char * str)43 parse_npt (const char *str)
44 {
45   int h=0,m=0, n;
46   float s;
47   double result;
48 
49   n = sscanf (str, "%d:%d:%f",  &h, &m, &s);
50   if (n == 3) {
51     goto done;
52   }
53 
54   n = sscanf (str, "%d:%f",  &m, &s);
55   if (n == 2) {
56     h = 0;
57     goto done;
58   }
59 
60   n = sscanf (str, "%f", &s);
61   if (n == 1) {
62     h = 0; m = 0;
63     goto sec_only;
64   }
65 
66   return -1.0;
67 
68  done:
69 
70   /* check valid time specs */
71   if (h < 0) return -1;
72   if (m > 59 || m < 0) return -1;
73   if (s >= 60.0 || s < 0) return -1;
74 
75  sec_only:
76 
77   result = ((h * 3600.0) + (m * 60.0) + s);
78 
79   return result;
80 }
81 
82 /* parse_smpte: parse a smpte-string */
83 static double
parse_smpte(const char * str,double framerate)84 parse_smpte(const char *str, double framerate)
85 {
86   int h = 0, m = 0, s = 0, n;
87   float frames;
88   double result;
89 
90   n = sscanf (str, "%d:%d:%d:%f", &h, &m, &s, &frames);
91   if (n == 4) {
92     goto done;
93   }
94 
95   n = sscanf (str, "%d:%d:%f", &m, &s, &frames);
96   if (n == 3) {
97     h = 0;
98     goto done;
99   }
100 
101   return -1.0;
102 
103  done:
104 
105   /* check valid time specs */
106   if (h < 0) return -1;
107   if (m > 59 || m < 0) return -1;
108   if (s > 59 || s < 0) return -1;
109   if (frames > (float)ceil(framerate) || frames < 0) return -1;
110 
111   result = ((h * 3600.0) + (m * 60.0) + s) + (frames/framerate);
112 
113   return result;
114 }
115 
116 double
parse_timespec(const char * str)117 parse_timespec (const char * str)
118 {
119   char timespec[16];
120 
121   if (str == NULL) return -1.0;
122 
123   if (sscanf (str, "npt:%16s", timespec) == 1) {
124     return parse_npt (timespec);
125   }
126 
127   if (sscanf (str, "smpte-24:%16s", timespec) == 1) {
128     return parse_smpte (timespec, 24.0);
129   }
130 
131   if (sscanf (str, "smpte-24-drop:%16s", timespec) == 1) {
132     return parse_smpte (timespec, 23.976);
133   }
134 
135   if (sscanf (str, "smpte-25:%16s", timespec) == 1) {
136     return parse_smpte (timespec, 25.0);
137   }
138 
139   if (sscanf (str, "smpte-30:%16s", timespec) == 1) {
140     return parse_smpte (timespec, 30.0);
141   }
142 
143   if (sscanf (str, "smpte-30-drop:%16s", timespec) == 1) {
144     return parse_smpte (timespec, 29.97);
145   }
146 
147   if (sscanf (str, "smpte-50:%16s", timespec) == 1) {
148     return parse_smpte (timespec, 50.0);
149   }
150 
151   if (sscanf (str, "smpte-60:%16s", timespec) == 1) {
152     return parse_smpte (timespec, 60);
153   }
154 
155   if (sscanf (str, "smpte-60-drop:%16s", timespec) == 1) {
156     return parse_smpte (timespec, 59.94);
157   }
158 
159   return parse_npt(str);
160 }
161