Convert 'encoding' parameter of certain proto_tree_add_item() calls in asn1 dissectors:
[obnox/wireshark/wip.git] / asn1 / mpeg-pes / packet-mpeg-pes-template.c
1 /* MPEG Packetized Elementary Stream (PES) packet decoder.
2  * Written by Shaun Jackman <sjackman@gmail.com>.
3  * Copyright 2007 Shaun Jackman
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <glib.h>
31
32 #include <epan/packet.h>
33 #include <epan/asn1.h>
34
35 #include "packet-per.h"
36
37 #include "packet-mpeg-pes-hf.c"
38 #include "packet-mpeg-pes-ett.c"
39 #include "packet-mpeg-pes-fn.c"
40
41 static int proto_mpeg = -1;
42 static int proto_mpeg_pes = -1;
43
44 static int ett_mpeg_pes_pack_header = -1;
45 static int ett_mpeg_pes_header_data = -1;
46 static int ett_mpeg_pes_trick_mode = -1;
47
48 static int hf_mpeg_pes_pack_header = -1;
49 static int hf_mpeg_pes_scr = -1;
50 static int hf_mpeg_pes_program_mux_rate = -1;
51 static int hf_mpeg_pes_stuffing_length = -1;
52 static int hf_mpeg_pes_stuffing = -1;
53 static int hf_mpeg_pes_extension = -1;
54 static int hf_mpeg_pes_header_data = -1;
55 static int hf_mpeg_pes_pts = -1;
56 static int hf_mpeg_pes_dts = -1;
57 static int hf_mpeg_pes_escr = -1;
58 static int hf_mpeg_pes_es_rate = -1;
59 static int hf_mpeg_pes_dsm_trick_mode = -1;
60 static int hf_mpeg_pes_dsm_trick_mode_control = -1;
61 static int hf_mpeg_pes_dsm_trick_mode_field_id = -1;
62 static int hf_mpeg_pes_dsm_trick_mode_intra_slice_refresh = -1;
63 static int hf_mpeg_pes_dsm_trick_mode_frequency_truncation = -1;
64 static int hf_mpeg_pes_dsm_trick_mode_rep_cntrl = -1;
65 static int hf_mpeg_pes_copy_info = -1;
66 static int hf_mpeg_pes_crc = -1;
67 static int hf_mpeg_pes_extension_flags = -1;
68 static int hf_mpeg_pes_private_data = -1;
69 static int hf_mpeg_pes_pack_length = -1;
70 static int hf_mpeg_pes_sequence = -1;
71 static int hf_mpeg_pes_pstd_buffer = -1;
72 static int hf_mpeg_pes_extension2 = -1;
73 static int hf_mpeg_pes_padding = -1;
74 static int hf_mpeg_pes_data = -1;
75
76 static int hf_mpeg_video_sequence_header = -1;
77 static int hf_mpeg_video_sequence_extension = -1;
78 static int hf_mpeg_video_group_of_pictures = -1;
79 static int hf_mpeg_video_picture = -1;
80 static int hf_mpeg_video_quantization_matrix = -1;
81 static int hf_mpeg_video_data = -1;
82
83 enum { PES_PREFIX = 1 };
84
85 enum {
86         STREAM_PICTURE = 0x00,
87         STREAM_SEQUENCE = 0xb3,
88         STREAM_SEQUENCE_EXTENSION = 0xb5,
89         STREAM_GOP = 0xb8,
90         STREAM_END = 0xb9,
91         STREAM_PACK = 0xba,
92         STREAM_SYSTEM = 0xbb,
93         STREAM_PROGRAM = 0xbc,
94         STREAM_PRIVATE1 = 0xbd,
95         STREAM_PADDING = 0xbe,
96         STREAM_PRIVATE2 = 0xbf,
97         STREAM_AUDIO = 0xc0,
98         STREAM_VIDEO = 0xe0
99 };
100
101 enum {
102         PTS_FLAG = 0x80,
103         DTS_FLAG = 0x40,
104         ESCR_FLAG = 0x20,
105         ES_RATE_FLAG = 0x10,
106         DSM_TRICK_MODE_FLAG = 0x08,
107         COPY_INFO_FLAG = 0x04,
108         CRC_FLAG = 0x02,
109         EXTENSION_FLAG = 0x01
110 };
111
112 enum {
113         PRIVATE_DATA_FLAG = 0x80,
114         PACK_LENGTH_FLAG = 0x40,
115         SEQUENCE_FLAG = 0x20,
116         PSTD_BUFFER_FLAG = 0x10,
117         MUST_BE_ONES = 0x07,
118         EXTENSION_FLAG2 = 0x01
119 };
120
121 enum {
122         FAST_FORWARD_CONTROL = 0x00,
123         SLOW_MOTION_CONTROL = 0x01,
124         FREEZE_FRAME_CONTROL = 0x02,
125         FAST_REVERSE_CONTROL = 0x03,
126         SLOW_REVERSE_CONTROL = 0x04
127 };
128
129 static const value_string mpeg_pes_TrickModeControl_vals[] = {
130   { FAST_FORWARD_CONTROL, "fast-forward" },
131   { SLOW_MOTION_CONTROL,  "slow-motion" },
132   { FREEZE_FRAME_CONTROL, "freeze-frame" },
133   { FAST_REVERSE_CONTROL, "fast-reverse" },
134   { SLOW_REVERSE_CONTROL, "slow-reverse" },
135   {   5, "reserved" },
136   {   6, "reserved" },
137   {   7, "reserved" },
138   {   0, NULL }
139 };
140
141 static const value_string mpeg_pes_TrickModeFieldId_vals[] = {
142   {   0, "display-from-top-field-only" },
143   {   1, "display-from-bottom-field-only" },
144   {   2, "display-complete-frame" },
145   {   3, "reserved" },
146   {   0, NULL }
147 };
148
149 static const value_string mpeg_pes_TrickModeIntraSliceRefresh_vals[] = {
150   {   0, "macroblocks-may-not-be-missing" },
151   {   1, "macroblocks-may-be-missing" },
152   {   0, NULL }
153 };
154
155 static const value_string mpeg_pes_TrickModeFrequencyTruncation_vals[] = {
156   {   0, "only-DC-coefficients-are-non-zero" },
157   {   1, "only-the-first-three-coefficients-are-non-zero" },
158   {   2, "only-the-first-six-coefficients-are-non-zero" },
159   {   3, "all-coefficients-may-be-non-zero" },
160   {   0, NULL }
161 };
162
163 #define TSHZ 90000
164
165 static guint64 decode_time_stamp(tvbuff_t *tvb, gint offset, nstime_t *nst)
166 {
167         guint64 bytes = tvb_get_ntoh40(tvb, offset);
168         guint64 ts =
169                 (bytes >> 33 & 0x0007) << 30 |
170                 (bytes >> 17 & 0x7fff) << 15 |
171                 (bytes >>  1 & 0x7fff) << 0;
172         unsigned rem = (unsigned)(ts % TSHZ);
173         nst->secs = (time_t)(ts / TSHZ);
174         nst->nsecs = (int)(G_GINT64_CONSTANT(1000000000) * rem / TSHZ);
175         return ts;
176 }
177
178 #define SCRHZ 27000000
179
180 static guint64 decode_clock_reference(tvbuff_t *tvb, gint offset,
181                 nstime_t *nst)
182 {
183         guint64 bytes = tvb_get_ntoh48(tvb, offset);
184         guint64 ts =
185                 (bytes >> 43 & 0x0007) << 30 |
186                 (bytes >> 27 & 0x7fff) << 15 |
187                 (bytes >> 11 & 0x7fff) << 0;
188         unsigned ext = (unsigned)((bytes >> 1) & 0x1ff);
189         guint64 cr = 300 * ts + ext;
190         unsigned rem = (unsigned)(cr % SCRHZ);
191         nst->secs = (time_t)(cr / SCRHZ);
192         nst->nsecs = (int)(G_GINT64_CONSTANT(1000000000) * rem / SCRHZ);
193         return cr;
194 }
195
196 static void
197 dissect_mpeg_pes_header_data(tvbuff_t *tvb, packet_info *pinfo,
198                 proto_tree *root, unsigned flags)
199 {
200         proto_item *item = proto_tree_add_item(root, hf_mpeg_pes_header_data, tvb,
201                         0, -1, ENC_NA);
202         proto_tree *tree = proto_item_add_subtree(item, ett_mpeg_pes_header_data);
203
204         gint offset = 0;
205         if (flags & PTS_FLAG) {
206                 nstime_t nst;
207                 decode_time_stamp(tvb, offset, &nst);
208                 proto_tree_add_time(tree, hf_mpeg_pes_pts, tvb,
209                                 offset, 5, &nst);
210                 offset += 5;
211
212                 if (check_col(pinfo->cinfo, COL_DEF_DST)) {
213                         SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL);
214                         col_add_fstr(pinfo->cinfo, COL_DEF_DST,
215                                         "PTS %ld.%09u",
216                                         (long) nst.secs, nst.nsecs);
217                 }
218         }
219         if (flags & DTS_FLAG) {
220                 nstime_t nst;
221                 decode_time_stamp(tvb, offset, &nst);
222                 proto_tree_add_time(tree, hf_mpeg_pes_dts, tvb,
223                                 offset, 5, &nst);
224                 offset += 5;
225
226                 if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
227                         SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
228                         col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
229                                         "DTS %ld.%09u",
230                                         (long) nst.secs, nst.nsecs);
231                 }
232         }
233         if (flags & ESCR_FLAG) {
234                 nstime_t nst;
235                 decode_clock_reference(tvb, offset, &nst);
236                 proto_tree_add_time(tree, hf_mpeg_pes_escr, tvb,
237                                 offset, 6, &nst);
238                 offset += 6;
239         }
240         if (flags & ES_RATE_FLAG) {
241                 unsigned es_rate = (tvb_get_ntohs(tvb, offset) >> 1 & 0x3fff) * 50;
242                 proto_tree_add_uint(tree, hf_mpeg_pes_es_rate, tvb,
243                                 offset, 3, es_rate);
244                 offset += 3;
245         }
246         if (flags & DSM_TRICK_MODE_FLAG)
247         {
248                 guint8 value = tvb_get_guint8(tvb, offset);
249                 guint8 control;
250                 proto_tree *trick_tree;
251                 proto_item *trick_item;
252
253                 trick_item = proto_tree_add_item(item,
254                         hf_mpeg_pes_dsm_trick_mode, tvb,
255                                 offset, 1, ENC_NA);
256
257                 trick_tree = proto_item_add_subtree(trick_item,
258                         ett_mpeg_pes_trick_mode);
259
260                 control = (value >> 5);
261                 proto_tree_add_uint(trick_tree,
262                         hf_mpeg_pes_dsm_trick_mode_control, tvb,
263                         offset, 1,
264                         control);
265
266                 if (control == FAST_FORWARD_CONTROL
267                         || control == FAST_REVERSE_CONTROL)
268                 {
269                         proto_tree_add_uint(trick_tree,
270                                 hf_mpeg_pes_dsm_trick_mode_field_id, tvb,
271                                 offset, 1,
272                                 (value & 0x18) >> 3);
273
274                         proto_tree_add_uint(trick_tree,
275                                 hf_mpeg_pes_dsm_trick_mode_intra_slice_refresh, tvb,
276                                 offset, 1,
277                                 (value & 0x04) >> 2);
278
279                         proto_tree_add_uint(trick_tree,
280                                 hf_mpeg_pes_dsm_trick_mode_frequency_truncation, tvb,
281                                 offset, 1,
282                                 (value & 0x03));
283                 }
284                 else if (control == SLOW_MOTION_CONTROL
285                         || control == SLOW_REVERSE_CONTROL)
286                 {
287                         proto_tree_add_uint(trick_tree,
288                                 hf_mpeg_pes_dsm_trick_mode_rep_cntrl, tvb,
289                                 offset, 1,
290                                 (value & 0x1F));
291                 }
292                 else if (control == FREEZE_FRAME_CONTROL)
293                 {
294                         proto_tree_add_uint(trick_tree,
295                                 hf_mpeg_pes_dsm_trick_mode_field_id, tvb,
296                                 offset, 1,
297                                 (value & 0x18) >> 3);
298                 }
299
300                 offset += 1;
301         }
302         if (flags & COPY_INFO_FLAG) {
303                 proto_tree_add_item(tree, hf_mpeg_pes_copy_info, tvb,
304                                 offset, 1, ENC_BIG_ENDIAN);
305                 offset++;
306         }
307         if (flags & CRC_FLAG) {
308                 proto_tree_add_item(tree, hf_mpeg_pes_crc, tvb,
309                                 offset, 2, ENC_BIG_ENDIAN);
310                 offset += 2;
311         }
312
313         if (flags & EXTENSION_FLAG) {
314                 int flags2 = tvb_get_guint8(tvb, offset);
315                 proto_tree_add_item(tree, hf_mpeg_pes_extension_flags, tvb,
316                                 offset, 1, ENC_BIG_ENDIAN);
317                 offset++;
318
319                 if (flags2 & PRIVATE_DATA_FLAG) {
320                         proto_tree_add_item(tree, hf_mpeg_pes_private_data, tvb,
321                                         offset, 2, ENC_BIG_ENDIAN);
322                         offset += 2;
323                 }
324                 if (flags2 & PACK_LENGTH_FLAG) {
325                         proto_tree_add_item(tree, hf_mpeg_pes_pack_length, tvb,
326                                         offset, 1, ENC_BIG_ENDIAN);
327                         offset++;
328                 }
329                 if (flags2 & SEQUENCE_FLAG) {
330                         proto_tree_add_item(tree, hf_mpeg_pes_sequence, tvb,
331                                         offset, 2, ENC_BIG_ENDIAN);
332                         offset += 2;
333                 }
334                 if (flags2 & PSTD_BUFFER_FLAG) {
335                         unsigned pstd = tvb_get_ntohs(tvb, offset);
336                         proto_tree_add_uint(tree, hf_mpeg_pes_pstd_buffer, tvb,
337                                         offset, 2, (pstd & 0x2000 ? 1024 : 128) * (pstd & 0x1ff));
338                         offset += 2;
339                 }
340                 if (flags2 & EXTENSION_FLAG2) {
341                         proto_tree_add_item(tree, hf_mpeg_pes_extension2, tvb,
342                                         offset, 2, ENC_BIG_ENDIAN);
343                         offset += 2;
344                 }
345         }
346 }
347
348 static gint
349 dissect_mpeg_pes_pack_header(tvbuff_t *tvb, gint offset,
350                 packet_info *pinfo, proto_tree *root)
351 {
352         unsigned program_mux_rate, stuffing_length;
353
354         proto_item *item = proto_tree_add_item(root, hf_mpeg_pes_pack_header, tvb,
355                         offset / 8, 10, ENC_NA);
356         proto_tree *tree = proto_item_add_subtree(item, ett_mpeg_pes_pack_header);
357
358         nstime_t nst;
359         decode_clock_reference(tvb, offset / 8, &nst);
360         proto_tree_add_time(tree, hf_mpeg_pes_scr, tvb, offset / 8, 6, &nst);
361         offset += 6 * 8;
362
363         program_mux_rate = (tvb_get_ntoh24(tvb, offset / 8) >> 2) * 50;
364         proto_tree_add_uint(tree, hf_mpeg_pes_program_mux_rate, tvb, offset / 8, 3,
365                         program_mux_rate);
366         offset += 3 * 8;
367
368         if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
369                 SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL);
370                 col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "%u B/s", program_mux_rate);
371         }
372
373         stuffing_length = tvb_get_guint8(tvb, offset / 8) & 0x07;
374         proto_tree_add_item(tree, hf_mpeg_pes_stuffing_length, tvb,
375                         offset / 8, 1, ENC_BIG_ENDIAN);
376         offset += 1 * 8;
377
378         if (stuffing_length > 0) {
379                 proto_tree_add_item(tree, hf_mpeg_pes_stuffing, tvb,
380                                 offset / 8, stuffing_length, ENC_NA);
381                 offset += stuffing_length * 8;
382         }
383
384         return offset;
385 }
386
387 static void
388 dissect_mpeg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
389
390 static gboolean
391 dissect_mpeg_pes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
392 {
393         int prefix;
394         int stream;
395         asn1_ctx_t asn1_ctx;
396         gint offset = 0;
397
398         if (!tvb_bytes_exist(tvb, 0, 3))
399                 return FALSE;   /* not enough bytes for a PES prefix */
400
401         prefix = tvb_get_ntoh24(tvb, 0);
402         if (prefix != PES_PREFIX)
403                 return FALSE;
404         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPEG PES");
405         col_clear(pinfo->cinfo, COL_INFO);
406
407         stream = tvb_get_guint8(tvb, 3);
408         if (check_col(pinfo->cinfo, COL_INFO)) {
409                 const char *s = match_strval(stream, mpeg_pes_T_stream_vals);
410                 if (s != NULL)
411                         col_set_str(pinfo->cinfo, COL_INFO, s);
412         }
413
414 #if 0
415         if (tree == NULL)
416                 return TRUE;
417 #endif
418         asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo);
419         offset = dissect_mpeg_pes_PES(tvb, offset, &asn1_ctx,
420                         tree, proto_mpeg_pes);
421
422         if (stream == STREAM_PICTURE) {
423                 int frame_type;
424
425                 frame_type = tvb_get_guint8(tvb, 5) >> 3 & 0x07;
426                 if (check_col(pinfo->cinfo, COL_INFO)) {
427                         const char *s = match_strval(frame_type,
428                                         mpeg_pes_T_frame_type_vals);
429                         if (s != NULL)
430                                 col_set_str(pinfo->cinfo, COL_INFO, s);
431                 }
432
433                 offset = dissect_mpeg_pes_Picture(tvb, offset, &asn1_ctx,
434                                 tree, hf_mpeg_video_picture);
435                 proto_tree_add_item(tree, hf_mpeg_video_data, tvb,
436                                 offset / 8, -1, ENC_NA);
437         } else if (stream == STREAM_SEQUENCE) {
438                 tvbuff_t *es;
439
440                 offset = dissect_mpeg_pes_Sequence_header(tvb, offset, &asn1_ctx,
441                                 tree, hf_mpeg_video_sequence_header);
442
443                 proto_tree_add_item(tree, hf_mpeg_video_quantization_matrix, tvb,
444                                 offset / 8, 64, ENC_NA);
445                 offset += 64 * 8;
446
447                 es = tvb_new_subset_remaining(tvb, offset / 8);
448                 dissect_mpeg_pes(es, pinfo, tree);
449         } else if (stream == STREAM_SEQUENCE_EXTENSION) {
450                 tvbuff_t *es;
451
452                 offset = dissect_mpeg_pes_Sequence_extension(tvb, offset, &asn1_ctx,
453                                 tree, hf_mpeg_video_sequence_extension);
454
455                 es = tvb_new_subset_remaining(tvb, offset / 8);
456                 dissect_mpeg_pes(es, pinfo, tree);
457         } else if (stream == STREAM_GOP) {
458                 tvbuff_t *es;
459
460                 offset = dissect_mpeg_pes_Group_of_pictures(tvb, offset, &asn1_ctx,
461                                 tree, hf_mpeg_video_group_of_pictures);
462
463                 es = tvb_new_subset_remaining(tvb, offset / 8);
464                 dissect_mpeg_pes(es, pinfo, tree);
465         } else if (stream == STREAM_PACK) {
466                 if (tvb_get_guint8(tvb, offset / 8) >> 6 == 1) {
467                         offset = dissect_mpeg_pes_pack_header(tvb, offset, pinfo, tree);
468                 } else {
469                         proto_tree_add_item(tree, hf_mpeg_pes_data, tvb,
470                                         offset / 8, 8, ENC_NA);
471                         offset += 8 * 8;
472                 }
473         } else if (stream == STREAM_SYSTEM || stream == STREAM_PRIVATE2) {
474                 unsigned data_length = tvb_get_ntohs(tvb, offset / 8);
475                 proto_tree_add_item(tree, hf_mpeg_pes_length, tvb,
476                                 offset / 8, 2, FALSE);
477                 offset += 2 * 8;
478
479                 proto_tree_add_item(tree, hf_mpeg_pes_data, tvb,
480                                 offset / 8, data_length, ENC_NA);
481         } else if (stream == STREAM_PADDING) {
482                 unsigned padding_length = tvb_get_ntohs(tvb, offset / 8);
483                 proto_tree_add_item(tree, hf_mpeg_pes_length, tvb,
484                                 offset / 8, 2, FALSE);
485                 offset += 2 * 8;
486
487                 proto_tree_add_item(tree, hf_mpeg_pes_padding, tvb,
488                                 offset / 8, padding_length, ENC_NA);
489         } else if (stream == STREAM_PRIVATE1
490                         || stream >= STREAM_AUDIO) {
491                 int length = tvb_get_ntohs(tvb, 4);
492
493                 if ((tvb_get_guint8(tvb, 6) & 0xc0) == 0x80) {
494                         int header_length;
495                         tvbuff_t *es;
496
497                         offset = dissect_mpeg_pes_Stream(tvb, offset, &asn1_ctx,
498                                         tree, hf_mpeg_pes_extension);
499                         /* https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=2229
500                          * A value of 0 indicates that the PES packet length is neither specified nor
501                          * bounded and is allowed only in PES packets whose payload is a video elementary
502                          * stream contained in Transport Stream packets.
503                          * XXX Some one with access to the spec should check this
504                          */
505                          if(length !=0 && stream != STREAM_VIDEO){
506                                  length -= 5 * 8;
507                          }
508
509                         header_length = tvb_get_guint8(tvb, 8);
510                         if (header_length > 0) {
511                                 int flags = tvb_get_guint8(tvb, 7);
512                                 tvbuff_t *header_data = tvb_new_subset(tvb, offset / 8,
513                                                 header_length, header_length);
514                                 dissect_mpeg_pes_header_data(header_data, pinfo, tree, flags);
515                                 offset += header_length * 8;
516                                  /* length may be zero for Video stream */
517                                 if(length !=0 && stream != STREAM_VIDEO){
518                                         length -= header_length * 8;
519                                 }
520                         }
521
522                         /* length may be zero for Video stream */
523                         if(length==0){
524                                 proto_tree_add_item(tree, hf_mpeg_pes_data, tvb, (offset>>3),-1, ENC_NA);
525                                 return TRUE;
526                         }
527
528                         es = tvb_new_subset(tvb, offset / 8, -1, length / 8);
529                         if (tvb_get_ntoh24(es, 0) == PES_PREFIX)
530                                 dissect_mpeg_pes(es, pinfo, tree);
531                         else if (tvb_get_guint8(es, 0) == 0xff)
532                                 dissect_mpeg(es, pinfo, tree);
533                         else
534                                 proto_tree_add_item(tree, hf_mpeg_pes_data, es,
535                                                 0, -1, ENC_NA);
536                 } else {
537                         unsigned data_length = tvb_get_ntohs(tvb, offset / 8);
538                         proto_tree_add_item(tree, hf_mpeg_pes_length, tvb,
539                                         offset / 8, 2, FALSE);
540                         offset += 2 * 8;
541
542                         proto_tree_add_item(tree, hf_mpeg_pes_data, tvb,
543                                         offset / 8, data_length, ENC_NA);
544                 }
545         } else {
546                 proto_tree_add_item(tree, hf_mpeg_pes_data, tvb,
547                                 offset / 8, -1, ENC_NA);
548         }
549         return TRUE;
550 }
551
552 static heur_dissector_list_t heur_subdissector_list;
553
554 static void
555 dissect_mpeg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
556 {
557     if (!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree)) {
558         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPEG");
559         col_clear(pinfo->cinfo, COL_INFO);
560         if (tree)
561             proto_tree_add_item(tree, proto_mpeg, tvb, 0, -1, FALSE);
562     }
563 }
564
565 void
566 proto_register_mpeg_pes(void)
567 {
568         static hf_register_info hf[] = {
569 #include "packet-mpeg-pes-hfarr.c"
570                 { &hf_mpeg_pes_pack_header,
571                         { "Pack header", "mpeg-pes.pack",
572                                 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
573                 { &hf_mpeg_pes_scr,
574                         { "system clock reference (SCR)", "mpeg-pes.scr",
575                                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }},
576                 { &hf_mpeg_pes_program_mux_rate,
577                         { "PES program mux rate", "mpeg-pes.program-mux-rate",
578                                 FT_UINT24, BASE_DEC, NULL, 0, NULL, HFILL }},
579                 { &hf_mpeg_pes_stuffing_length,
580                         { "PES stuffing length", "mpeg-pes.stuffing-length",
581                                 FT_UINT8, BASE_DEC, NULL, 0x07, NULL, HFILL }},
582                 { &hf_mpeg_pes_stuffing,
583                         { "PES stuffing bytes", "mpeg-pes.stuffing",
584                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
585                 { &hf_mpeg_pes_extension,
586                         { "PES extension", "mpeg-pes.extension",
587                                 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
588                 { &hf_mpeg_pes_header_data,
589                         { "PES header data", "mpeg-pes.header-data",
590                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
591                 { &hf_mpeg_pes_pts,
592                         { "presentation time stamp (PTS)", "mpeg-pes.pts",
593                                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }},
594                 { &hf_mpeg_pes_dts,
595                         { "decode time stamp (DTS)", "mpeg-pes.dts",
596                                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }},
597                 { &hf_mpeg_pes_escr,
598                         { "elementary stream clock reference (ESCR)", "mpeg-pes.escr",
599                                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }},
600                 { &hf_mpeg_pes_es_rate,
601                         { "elementary stream rate", "mpeg-pes.es-rate",
602                                 FT_UINT24, BASE_DEC, NULL, 0x7ffe, NULL, HFILL }},
603                 { &hf_mpeg_pes_dsm_trick_mode,
604                         { "Trick mode", "mpeg-pes.trick-mode",
605                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
606                 { &hf_mpeg_pes_dsm_trick_mode_control,
607                         { "control", "mpeg-pes.trick-mode-control",
608                                 FT_UINT8, BASE_HEX, VALS(mpeg_pes_TrickModeControl_vals), 0,
609                                 "mpeg_pes trick mode control", HFILL }},
610                 { &hf_mpeg_pes_dsm_trick_mode_field_id,
611                         { "field id", "mpeg-pes.trick-mode-field-id",
612                                 FT_UINT8, BASE_HEX, VALS(mpeg_pes_TrickModeFieldId_vals), 0,
613                                 "mpeg_pes trick mode field id", HFILL }},
614                 { &hf_mpeg_pes_dsm_trick_mode_intra_slice_refresh,
615                         { "intra slice refresh", "mpeg-pes.trick-mode-intra-slice-refresh",
616                                 FT_UINT8, BASE_HEX, VALS(mpeg_pes_TrickModeIntraSliceRefresh_vals), 0,
617                                 "mpeg_pes trick mode intra slice refresh", HFILL }},
618                 { &hf_mpeg_pes_dsm_trick_mode_frequency_truncation,
619                         { "frequency truncation", "mpeg-pes.trick-mode-frequeny-truncation",
620                                 FT_UINT8, BASE_HEX, VALS(mpeg_pes_TrickModeFrequencyTruncation_vals), 0,
621                                 "mpeg_pes trick mode frequency truncation", HFILL }},
622                 { &hf_mpeg_pes_dsm_trick_mode_rep_cntrl,
623                         { "rep cntrl", "mpeg-pes.trick-mode-rep-cntrl",
624                                 FT_UINT8, BASE_HEX, NULL, 0, "mpeg_pes trick mode rep cntrl", HFILL }},
625                 { &hf_mpeg_pes_copy_info,
626                         { "copy info", "mpeg-pes.copy-info",
627                                 FT_UINT8, BASE_DEC, NULL, 0x7f, NULL, HFILL }},
628                 { &hf_mpeg_pes_crc,
629                         { "CRC", "mpeg-pes.crc",
630                                 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
631                 { &hf_mpeg_pes_extension_flags,
632                         { "extension flags", "mpeg-pes.extension-flags",
633                                 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
634                 { &hf_mpeg_pes_private_data,
635                         { "private data", "mpeg-pes.private-data",
636                                 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
637                 { &hf_mpeg_pes_pack_length,
638                         { "pack length", "mpeg-pes.pack-length",
639                                 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
640                 { &hf_mpeg_pes_sequence,
641                         { "sequence", "mpeg-pes.sequence",
642                                 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
643                 { &hf_mpeg_pes_pstd_buffer,
644                         { "P-STD buffer size", "mpeg-pes.pstd-buffer",
645                                 FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
646                 { &hf_mpeg_pes_extension2,
647                         { "extension2", "mpeg-pes.extension2",
648                                 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
649                 { &hf_mpeg_pes_padding,
650                         { "PES padding", "mpeg-pes.padding",
651                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
652                 { &hf_mpeg_pes_data,
653                         { "PES data", "mpeg-pes.data",
654                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
655                 { &hf_mpeg_video_sequence_header,
656                         { "MPEG sequence header", "mpeg-video.sequence",
657                                 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
658                 { &hf_mpeg_video_sequence_extension,
659                         { "MPEG sequence extension", "mpeg-video.sequence-ext",
660                                 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
661                 { &hf_mpeg_video_group_of_pictures,
662                         { "MPEG group of pictures", "mpeg-video.gop",
663                                 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
664                 { &hf_mpeg_video_picture,
665                         { "MPEG picture", "mpeg-video.picture",
666                                 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
667                 { &hf_mpeg_video_quantization_matrix,
668                         { "MPEG quantization matrix", "mpeg-video.quant",
669                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
670                 { &hf_mpeg_video_data,
671                         { "MPEG picture data", "mpeg-video.data",
672                                 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
673         };
674
675         static gint *ett[] = {
676 #include "packet-mpeg-pes-ettarr.c"
677                 &ett_mpeg_pes_pack_header,
678                 &ett_mpeg_pes_header_data,
679                 &ett_mpeg_pes_trick_mode
680         };
681
682         proto_mpeg = proto_register_protocol(
683                         "Moving Picture Experts Group", "MPEG", "mpeg");
684         register_dissector("mpeg", dissect_mpeg, proto_mpeg);
685         register_heur_dissector_list("mpeg", &heur_subdissector_list);
686
687         proto_mpeg_pes = proto_register_protocol(
688                         "Packetized Elementary Stream", "MPEG PES", "mpeg-pes");
689         proto_register_field_array(proto_mpeg_pes, hf, array_length(hf));
690         proto_register_subtree_array(ett, array_length(ett));
691         new_register_dissector("mpeg-pes", dissect_mpeg_pes, proto_mpeg_pes);
692 }
693
694 void
695 proto_reg_handoff_mpeg_pes(void)
696 {
697         dissector_handle_t mpeg_handle = find_dissector("mpeg");
698
699         dissector_add_uint("wtap_encap", WTAP_ENCAP_MPEG, mpeg_handle);
700         heur_dissector_add("mpeg", dissect_mpeg_pes, proto_mpeg_pes);
701 }