diff options
Diffstat (limited to 'src/plugins/mpeg_extractor.c')
-rw-r--r-- | src/plugins/mpeg_extractor.c | 171 |
1 files changed, 94 insertions, 77 deletions
diff --git a/src/plugins/mpeg_extractor.c b/src/plugins/mpeg_extractor.c index 6c68b4a..dfc7ecb 100644 --- a/src/plugins/mpeg_extractor.c +++ b/src/plugins/mpeg_extractor.c | |||
@@ -1,11 +1,11 @@ | |||
1 | 1 | ||
2 | /* | 2 | /* |
3 | This file is part of libextractor. | 3 | This file is part of libextractor. |
4 | (C) 2004, 2005, 2006, 2009 Vidyut Samanta and Christian Grothoff | 4 | (C) 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff |
5 | 5 | ||
6 | libextractor is free software; you can redistribute it and/or modify | 6 | libextractor is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published | 7 | it under the terms of the GNU General Public License as published |
8 | by the Free Software Foundation; either version 2, or (at your | 8 | by the Free Software Foundation; either version 3, or (at your |
9 | option) any later version. | 9 | option) any later version. |
10 | 10 | ||
11 | libextractor is distributed in the hope that it will be useful, but | 11 | libextractor is distributed in the hope that it will be useful, but |
@@ -19,98 +19,115 @@ | |||
19 | Boston, MA 02111-1307, USA. | 19 | Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /** | ||
23 | * @file plugins/mpeg_extractor.c | ||
24 | * @brief plugin to support MPEG files | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
22 | #include "platform.h" | 27 | #include "platform.h" |
23 | #include "extractor.h" | 28 | #include "extractor.h" |
24 | #include <mpeg2dec/mpeg2.h> | 29 | #include <mpeg2dec/mpeg2.h> |
25 | 30 | ||
26 | #define ADD(s,t) do { if (0 != (ret = proc (proc_cls, "mpeg", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1))) goto EXIT; } while (0) | 31 | |
32 | /** | ||
33 | * Give meta data to extractor. | ||
34 | * | ||
35 | * @param t type of the meta data | ||
36 | * @param s meta data value in utf8 format | ||
37 | */ | ||
38 | #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "mpeg", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) goto EXIT; } while (0) | ||
27 | 39 | ||
28 | 40 | ||
29 | /* video/mpeg */ | 41 | /** |
30 | int | 42 | * Main entry method for the 'video/mpeg' extraction plugin. |
31 | EXTRACTOR_mpeg_extract (const unsigned char *data, | 43 | * |
32 | size_t size, | 44 | * @param ec extraction context provided to the plugin |
33 | EXTRACTOR_MetaDataProcessor proc, | 45 | */ |
34 | void *proc_cls, | 46 | void |
35 | const char *options) | 47 | EXTRACTOR_mpeg_extract_method (struct EXTRACTOR_ExtractContext *ec) |
36 | { | 48 | { |
37 | mpeg2dec_t *handle; | 49 | mpeg2dec_t *handle; |
38 | uint8_t *start; | ||
39 | uint8_t *end; | ||
40 | const mpeg2_info_t *info; | 50 | const mpeg2_info_t *info; |
51 | void *buf; | ||
52 | ssize_t avail; | ||
41 | mpeg2_state_t state; | 53 | mpeg2_state_t state; |
42 | int ret; | ||
43 | char format[256]; | 54 | char format[256]; |
55 | int finished; | ||
44 | 56 | ||
45 | if ((size < 4) || | 57 | if (NULL == (handle = mpeg2_init ())) |
46 | (!((data[0] == 0x00) && | 58 | return; |
47 | (data[1] == 0x00) && | 59 | if (NULL == (info = mpeg2_info (handle))) |
48 | (data[2] == 0x01) && ((data[3] == 0xB3) || (data[3] == 0xBA))))) | ||
49 | return 0; | ||
50 | |||
51 | handle = mpeg2_init (); | ||
52 | if (handle == NULL) | ||
53 | return 0; | ||
54 | start = (uint8_t *) data; | ||
55 | end = (uint8_t *) & data[size]; | ||
56 | mpeg2_buffer (handle, start, end); | ||
57 | state = mpeg2_parse (handle); | ||
58 | if (state != STATE_SEQUENCE) | ||
59 | { | 60 | { |
60 | mpeg2_close (handle); | 61 | mpeg2_close (handle); |
61 | return 0; | 62 | return; |
62 | } | 63 | } |
63 | info = mpeg2_info (handle); | 64 | finished = 3; |
64 | if (info == NULL) | 65 | while (0 != finished) |
65 | { | 66 | { |
66 | mpeg2_close (handle); | 67 | state = mpeg2_parse (handle); |
67 | return 0; | 68 | switch (state) |
68 | } | 69 | { |
69 | ret = 0; | 70 | case STATE_BUFFER: |
70 | ADD ("video/mpeg", EXTRACTOR_METATYPE_MIMETYPE); | 71 | if (0 >= (avail = ec->read (ec->cls, |
71 | if (info->sequence != NULL) | 72 | &buf, |
72 | { | 73 | 16 * 1024))) |
73 | snprintf (format, | 74 | goto EXIT; |
74 | sizeof(format), "%ux%u", | 75 | mpeg2_buffer (handle, buf, buf + avail); |
75 | info->sequence->width, info->sequence->height); | 76 | break; |
76 | ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); | 77 | case STATE_SEQUENCE: |
77 | switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) | 78 | ADD ("video/mpeg", EXTRACTOR_METATYPE_MIMETYPE); |
78 | { | 79 | snprintf (format, |
79 | case SEQ_VIDEO_FORMAT_PAL: | 80 | sizeof(format), "%ux%u", |
80 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 81 | info->sequence->width, info->sequence->height); |
81 | break; | 82 | ADD (format, EXTRACTOR_METATYPE_IMAGE_DIMENSIONS); |
82 | case SEQ_VIDEO_FORMAT_NTSC: | 83 | switch (info->sequence->flags & SEQ_VIDEO_FORMAT_UNSPECIFIED) |
83 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 84 | { |
84 | break; | 85 | case SEQ_VIDEO_FORMAT_PAL: |
85 | case SEQ_VIDEO_FORMAT_SECAM: | 86 | ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
86 | ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 87 | break; |
87 | break; | 88 | case SEQ_VIDEO_FORMAT_NTSC: |
88 | case SEQ_VIDEO_FORMAT_MAC: | 89 | ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
89 | ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); | 90 | break; |
90 | break; | 91 | case SEQ_VIDEO_FORMAT_SECAM: |
91 | default: | 92 | ADD ("SECAM", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
92 | break; | 93 | break; |
93 | } | 94 | case SEQ_VIDEO_FORMAT_MAC: |
94 | if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0) | 95 | ADD ("MAC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM); |
95 | ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION); | 96 | break; |
96 | else | 97 | default: |
97 | ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION); | 98 | break; |
98 | } | 99 | } |
99 | if (info->gop != NULL) | 100 | if ((info->sequence->flags & SEQ_FLAG_MPEG2) > 0) |
100 | { | 101 | ADD ("MPEG2", EXTRACTOR_METATYPE_FORMAT_VERSION); |
101 | /* this usually does not work yet, since gop's are not | 102 | else |
102 | often at the beginning of the stream (and we | 103 | ADD ("MPEG1", EXTRACTOR_METATYPE_FORMAT_VERSION); |
103 | don't iterate over the stream hoping to find one). | 104 | finished &= ~2; |
104 | Hence we usually don't get the size. Not sure how | 105 | break; |
105 | to *efficiently* get the gop (without scanning | 106 | case STATE_GOP: |
106 | through the entire file) */ | 107 | if ( (NULL != info->gop) && |
107 | snprintf (format, | 108 | (0 != info->gop->pictures) ) |
108 | sizeof(format), "%u:%u:%u (%u frames)", | 109 | { |
109 | info->gop->hours, | 110 | snprintf (format, |
110 | info->gop->minutes, info->gop->seconds, info->gop->pictures); | 111 | sizeof(format), |
111 | ADD (format, EXTRACTOR_METATYPE_DURATION); | 112 | "%u:%u:%u (%u frames)", |
113 | info->gop->hours, | ||
114 | info->gop->minutes, info->gop->seconds, info->gop->pictures); | ||
115 | ADD (format, EXTRACTOR_METATYPE_DURATION); | ||
116 | finished &= ~1; | ||
117 | } | ||
118 | break; | ||
119 | case STATE_SLICE: | ||
120 | break; | ||
121 | case STATE_END: | ||
122 | break; | ||
123 | case STATE_INVALID: | ||
124 | goto EXIT; | ||
125 | default: | ||
126 | break; | ||
127 | } | ||
112 | } | 128 | } |
113 | EXIT: | 129 | EXIT: |
114 | mpeg2_close (handle); | 130 | mpeg2_close (handle); |
115 | return ret; | ||
116 | } | 131 | } |
132 | |||
133 | /* end of mpeg_extractor.c */ | ||