MPL: Difference between revisions

From MultimediaWiki
Jump to navigation Jump to search
(initial site for MPL(S))
 
 
(42 intermediate revisions by the same user not shown)
Line 2: Line 2:
* This is a playlist file used in BluRays and AVCHD (Lite) video camcorders and foto cams.
* This is a playlist file used in BluRays and AVCHD (Lite) video camcorders and foto cams.


'''Please correct or beautify the language used in this article!'''
== Introduction ==
This site tries to collect information about this file. This information partly comes from reverse engineering. There is no free specification available on the net.
The intention was to extract the time stamps of the captured videos from the mpl files. The Panasonic GH1 doesn't write the time stamp into the SEI part of the h264 stream. Other cams are known to do this (e.g. Canon HG-20):
http://forum.videohelp.com/threads/296805-Reading-AVCHD-Playlist-files-BDMV-Playlist-*-mpl
This document might be helpful to understand the connection between a playlist file a cpi file and the actual stream file.
http://www.blu-raydisc.com/Assets/Downloadablefile/BD-RE_Part3_V2.1_WhitePaper_080406-15271.pdf


This site tries to collect information about this file. This information partly comes from reverse engineering. There is no free specification available on the net.
= Technical Part =


The file is located in a directory structure like this:
The file is located in a directory structure like this:
Line 9: Line 20:
it corresponds with the files in this directory:
it corresponds with the files in this directory:
  /BDMV/STREAM/00000.MTS
  /BDMV/STREAM/00000.MTS
In Bluray specification the files hav a differnt endig: *.mpls and *.m2ts.


The following information are reverse engineered from MPL files from a [[Panasonic]] GH1 foto cam.
The following information are reverse engineered from MPL files from a [[Panasonic]] GH1 foto cam.


The following file sizes are known:
This file sizes are known:
* 638 bytes
* 638 bytes
* 800 bytes
* 800 bytes
Line 29: Line 42:
The values are written only when they are equal in every file.
The values are written only when they are equal in every file.


Header
  M2TS File Meta Data [1]
  M2TS File Meta Data [2]
  ...
  Next Part 1
  Next Part 2 [2]                only there when more than one file is described in this document
  Next Part 2 [3]
  ...
  PLEX Part
  Next Part 3
  Video Part [1]
  Video Part [2]
  ...
  Trailer
=== Header ===
=== Header ===
  char[4] 'MPLS'            FOURCC?
  char[4] 'MPLS'            FOURCC?
Line 37: Line 64:


  char[2] {0, 0}
  char[2] {0, 0}
  char[2]                  this corresponds with the file size
  char[2]                  this corresponds with the file size differs from the former one
  char[12] {0, 0, ...}
  char[12] {0, 0, ...}


Line 55: Line 82:
=== M2TS File Meta Data ? ===
=== M2TS File Meta Data ? ===
This part ist contained X-times and is 82 bytes in size.  
This part ist contained X-times and is 82 bytes in size.  
The correpsonding M2TS file name on the Panasonic is 00012.MTS.
The corresponding M2TS file name on the Panasonic is 00012.MTS.


  char[2] {0, 'P'}
  char[2] {0, 'P'}
Line 83: Line 110:


  char[4] {5, 0x81, 0x31, 0x75}
  char[4] {5, 0x81, 0x31, 0x75}
  char[2] {0xE6, 0x64}
  char[2] {0x6E, 0x64}


=== Next Part ===
=== Next Part 1 ===
TBD
unknown contents


Somwhere in the file are time stamps coded for the corresponding MTS files.
char[4] {0, 0, 0, A}                        A corresponds with file size
This part has the following syntax:
char[4] {0, B, 0, 1}                        B = number of described MTS files
  char[2]                   either {0xFF, 0xFF} or {A, B}
char[4] {0, 0, 0, 0}
  char   {0x1E}
char[4] {0x40, 0x74, 0xFF, 0xFF}
  char                  BCD century
 
  char                  BCD decade
=== Next Part 2 ===
  char                  BCD month
This part is 14 bytes in size. One of this parts is inlcuded for each file description starting with the second.
  char                  BCD day
 
  char                  BCD hour
char[4] {0, 0, 0, 0}
  char                  BCD minute
char[4] {0, 1, 0, A}            A = number of description
  char                  BCD second
char[4] {0, 0, _, _}
  char[2] {0x90, 0x0A}
char[2] {0xFF, 0xFF}
  char[11]             date as string (null terminated; no time) e.g. "2010. 4.18"
 
A and B corresponding with the MTS file name. e.g. (A<<16 + B).MTS = 00012.MTS, A=0, B=0x0C
=== PLEX Part ===
BCD = Binary Coded Decimal
unknown contents
 
char[4] {0, 0, 0, 0}
char[4] {0, _, _, _}                       
char[4] {0, 0, 0, 0x18}
char[4] {0, 0, 0, 1}
 
char[4] {0x10, 0, 1, 0}
char[4] {0, 0, 0, 0x18}
char[4] {0, 0, _, _}
char[4] 'PLEX'
 
char[4] {0, 0, 0, 0}
char[4] {0, 0, 01, 0x44}
char[4] {0, 0, _, _}
char[4] {0, 0, 0, 0}
 
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
 
char[4] {0, 0, 0, 0}
char[4] {0, 0, 1, 0x18}
char[4] {1, 3, 5, 0x18}
char[4] {0, 0, 0, 0}
 
char[2] {0xFF, 0xFF}
 
=== Next Part 3 ===
This part is 276 bytes in size.
 
It cntains a time stamp that might be the time when the file was closed by the cam.
 
char[1] {0x1E}
char[1] {C}                  C = BCD (Century)
char[1] {D}                  D = BCD (Decade)
char[1] {E}                  E = BCD (Month)
char[1] {F}                  F = BCD (Day)
char[1] {G}                  G = BCD (Hour)
char[1] {H}                  H = BCD (Minute)
char[1] {I}                  I = BCD (Second)
char[2] {0x90, 0x0A}  or  {0x90, 0x0C}
char[10]                    date as string (no time) e.g. '2010. 4.18'
char[4] {0, 0, 0, 0}
...
char[4] {0, 0, 0, 0}       
...
char[4] {0, 0, 0, 0}       
char[1] {0, _, 0, A}        A = number of Video Parts following
 
=== Video Part ===
This part contains time stamps of the corresponding MTS file. Right before the first occurance of one of such part is a char that tells how many such parts are following.
 
This part is 66 bytes in size.
 
char[4] {1, 3, 5, 0x81}
  char[4] {0, 0, 0, 0}
char[2] {A, B}               (A<<8 + B).MTS = 00012.MTS, A=0, B=0x0C;
  char[1] {0x1E}
  char[1] {C}                 C = BCD (Century)
  char[1] {D}                 D = BCD (Decade)
  char[1] {E}                 E = BCD (Month)
  char[1] {F}                 F = BCD (Day)
  char[1] {G}                 G = BCD (Hour)
 
  char[1] {H}                 H = BCD (Minute)
  char[1] {I}                 I = BCD (Second)
  char[2] {0x90, 0x0A} or {0x90, 0x0C}
  char[10]                     date as string (no time) e.g. '2010. 4.18'
char[2] {0, 0}
 
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0x11, 0x10, 0, 0}
 
char[4] {0, I, J, _}        I = 0x65 or 0x66; J=2 for SH or 0 for FHD
char[1] {0x03}
char[3] 'FHD'; 'SH\0'        video format
char[4] {0, 0, 0, 0}
char[4] {0xFF, 0xFF, 0xFF, 0xFF}
 
char[2] {0, 0}
 
A and B tell the name of the corresponding MTS file e.g. (A<<8 + B).MTS = 00012.MTS, A=0, B=0x0C
 
=== Trailer ===
This part is 50 bytes in size.
 
char[4] {0, 0, 0, 0}
char[4] {_, _, _, _}
...
char[4] {_, _, _, _}
char[4] {0, 0, 0, 0}
char[2] {0, 0}
 
== Definitions ==
; BCD
: Binary Coded Decimal
; _
: unknow but different in different files
; FHD
: Full HD Quality (1080p25)
; SH
: Super High Quality (720p50)


[[Category:Meta Format]]
[[Category:Meta Format]]
= Time Stamp Parser =
This is a small C programm to parse all time stamps of MTS files that are written in playlist files in a directory. This programm is developed based on this file:
http://www.avsforum.com/avs-vb/showthread.php?p=14578210#post14578210
/* GPL 2.1 © Elte 2011 */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#define VERSION        "0.1"
#define SIGNATUR        "MPLS0100"
typedef struct {
    unsigned char decade, month, day, hour, minute, second;
} MTS_date;
int main (int argc, char *argv[])
{
    struct dirent  *dp = NULL;
    DIR      *dir_ptr = NULL;
    FILE *mpl_file_ptr = NULL;
    int ret = 0;
    unsigned char signatur[] = SIGNATUR, buffer[sizeof(SIGNATUR)];
    if (argc != 2) {
        fprintf(stderr, "Version: %s\n", VERSION);
        fprintf(stderr, "Usage: %s <path to folder containing *.MPL files\n", argv[0]);
        goto ERROR;
    }
    if (chdir(argv[1]) == -1) {
fprintf(stderr, "Cannot change directory: %s %s\n", argv[1], strerror(errno));
goto ERROR;
    }
    if ((dir_ptr = opendir (".")) == NULL) {
        fprintf (stderr, "Error reading directory: %s %s\n", argv[1], strerror(errno));
        goto ERROR;
    }
//    printf (" STREAM      DATE      TIME\n");
//    printf ("---------  ----------  --------\n");
    while ((dp = readdir(dir_ptr)) != NULL) {
        if (!strncmp ((dp->d_name) + (strlen (dp->d_name) - 4), ".MPL", 4)) {
            unsigned char file_number[2] = {0, 0},
                                num_desc = 0;
            MTS_date                this = {0, 0, 0, 0, 0, 0};
            if ((mpl_file_ptr = fopen (dp->d_name, "r")) == NULL) {
                fprintf (stderr, "Error opening file: %s %s\n", dp->d_name, strerror(errno));
                goto NEXT_FILE;
            }
            if ((fread (buffer, sizeof(SIGNATUR), 1, mpl_file_ptr) != 1) ||
                (strncmp (buffer, SIGNATUR, sizeof(SIGNATUR)))) {
                fprintf (stderr, "Could not read file signatur. Wrong filetype?\n");
                goto NEXT_FILE;
            }
            // find out how many mts files are described
            // the 66th byte contains this number
            fseek (mpl_file_ptr, 66 - sizeof(SIGNATUR) - 1, SEEK_CUR);
            ret = fgetc(mpl_file_ptr);
            if (ret != EOF) {
                num_desc = (unsigned char) ret;
            } else {
                fprintf (stderr, "Could not read contents\n");
                goto NEXT_FILE;
            }
            // jump to the first occurance of a time stamp and print it
            // iterate till all num_desc time stamps are shown
            // trailer = 50 bytes
            // mts description = 66 bytes
            // actual info starts at 9th byte of mts description
            fseek (mpl_file_ptr, -50 - 66*num_desc - 48 +2, SEEK_END);
            while (num_desc > 0) {
                int i;
                const unsigned char time_stamp_sig[] = {1, 3, 5, 0x81, 0, 0, 0, 0};
                num_desc--;
                fseek (mpl_file_ptr, 48, SEEK_CUR);
                // scan for time stamp signatur
                for (i=0; i<8; i++) {
                    if ((ret = fgetc(mpl_file_ptr)) != time_stamp_sig[i]) {
                        fprintf (stderr, "Could not parse contents\n");
                        goto NEXT_FILE;
                    }
                }
                // scan time stamp
                if ((ret = fscanf (mpl_file_ptr, "%c%c\x1E%*1[ ]%c%c%c%c%c%c",
                              &file_number[0], &file_number[1],
                              &this.decade, &this.month, &this.day,
                              &this.hour, &this.minute, &this.second)) != 8) {
                    fprintf (stderr, "Could not parse time stamp\n");
                    goto NEXT_FILE;
                }
                printf ("%.5d.MTS  20%.2X/%.2X/%.2X  %.2X:%.2X:%.2X\n",
                        (file_number[0]<<8) + file_number[1],
                        this.decade, this.month, this.day,
                        this.hour, this.minute, this.second);
            }
NEXT_FILE:
            fclose (mpl_file_ptr);
        }
    }
ERROR:
    closedir (dir_ptr);
}

Latest revision as of 07:03, 31 January 2011

  • Extensions: mpl, mpls
  • This is a playlist file used in BluRays and AVCHD (Lite) video camcorders and foto cams.

Please correct or beautify the language used in this article!

Introduction

This site tries to collect information about this file. This information partly comes from reverse engineering. There is no free specification available on the net.

The intention was to extract the time stamps of the captured videos from the mpl files. The Panasonic GH1 doesn't write the time stamp into the SEI part of the h264 stream. Other cams are known to do this (e.g. Canon HG-20):

http://forum.videohelp.com/threads/296805-Reading-AVCHD-Playlist-files-BDMV-Playlist-*-mpl

This document might be helpful to understand the connection between a playlist file a cpi file and the actual stream file.

http://www.blu-raydisc.com/Assets/Downloadablefile/BD-RE_Part3_V2.1_WhitePaper_080406-15271.pdf

Technical Part

The file is located in a directory structure like this:

/BDMV/PLAYLIST/00000.MPL

it corresponds with the files in this directory:

/BDMV/STREAM/00000.MTS

In Bluray specification the files hav a differnt endig: *.mpls and *.m2ts.

The following information are reverse engineered from MPL files from a Panasonic GH1 foto cam.

This file sizes are known:

  • 638 bytes
  • 800 bytes
  • 962 bytes
  • 1124 bytes
  • 1286 bytes
  • 1448 bytes
  • 1772 bytes
  • 2096 bytes
  • 2420 bytes

The difference in size is always a multiple of 162 bytes.

File Structure

The values are written only when they are equal in every file.

Header
 M2TS File Meta Data [1]
 M2TS File Meta Data [2]
 ...
 Next Part 1
 Next Part 2 [2]                only there when more than one file is described in this document
 Next Part 2 [3]
 ...
 PLEX Part
 Next Part 3
 Video Part [1]
 Video Part [2]
 ...
 Trailer

Header

char[4] 'MPLS'            FOURCC?
char[4] '0100'            might be version number
char[4] {0, 0, 0, 0x3A}
char[2] {0, 0}
char[2]                   this corresponds with the file size
char[2] {0, 0}
char[2]                   this corresponds with the file size differs from the former one
char[12] {0, 0, ...}
char[8] {0, 0, ...}
char[4] {0, 0, 0, 0x0E}
char[4] {0, 1, 0, 0}
char[4] {0, 0, 1, 0xCF}
char[4] {0x40, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[2]                    this corresponds with the file size
char[2] {0, 0}
char[2] {0, X}             file size = 476 + 162*X in bytes
char[2] {0, 0}

M2TS File Meta Data ?

This part ist contained X-times and is 82 bytes in size. The corresponding M2TS file name on the Panasonic is 00012.MTS.

char[2] {0, 'P'}
char[10] "00012M2TS"       this is a null terminated string of the corresponding MTS file name (without dot '.')
char[4] {1, 0, 0, 0}
char[2] {0x40, 0x74}
char[2]
char[2]
char[2] {0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0x2E}
char[4] {0, 0, 1, 1}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 9, 1}
char[4] {0x10, 0x11, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {5, 0x1B, 0x43, 0}
char[4] {0, 0, 9, 1}
char[4] {0x11, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {5, 0x81, 0x31, 0x75}
char[2] {0x6E, 0x64}

Next Part 1

unknown contents

char[4] {0, 0, 0, A}                         A corresponds with file size
char[4] {0, B, 0, 1}                         B = number of described MTS files
char[4] {0, 0, 0, 0}
char[4] {0x40, 0x74, 0xFF, 0xFF}

Next Part 2

This part is 14 bytes in size. One of this parts is inlcuded for each file description starting with the second.

char[4] {0, 0, 0, 0}
char[4] {0, 1, 0, A}             A = number of description
char[4] {0, 0, _, _}
char[2] {0xFF, 0xFF}

PLEX Part

unknown contents

char[4] {0, 0, 0, 0}
char[4] {0, _, _, _}                        
char[4] {0, 0, 0, 0x18}
char[4] {0, 0, 0, 1}
char[4] {0x10, 0, 1, 0}
char[4] {0, 0, 0, 0x18}
char[4] {0, 0, _, _}
char[4] 'PLEX'
char[4] {0, 0, 0, 0}
char[4] {0, 0, 01, 0x44}
char[4] {0, 0, _, _}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 1, 0x18}
char[4] {1, 3, 5, 0x18}
char[4] {0, 0, 0, 0}
char[2] {0xFF, 0xFF}

Next Part 3

This part is 276 bytes in size.

It cntains a time stamp that might be the time when the file was closed by the cam.

char[1] {0x1E}
char[1] {C}                  C = BCD (Century)
char[1] {D}                  D = BCD (Decade)
char[1] {E}                  E = BCD (Month)
char[1] {F}                  F = BCD (Day)
char[1] {G}                  G = BCD (Hour)
char[1] {H}                  H = BCD (Minute)
char[1] {I}                  I = BCD (Second)
char[2] {0x90, 0x0A}  or  {0x90, 0x0C}
char[10]                     date as string (no time) e.g. '2010. 4.18'
char[4] {0, 0, 0, 0}
...
char[4] {0, 0, 0, 0}         
...
char[4] {0, 0, 0, 0}         
char[1] {0, _, 0, A}         A = number of Video Parts following

Video Part

This part contains time stamps of the corresponding MTS file. Right before the first occurance of one of such part is a char that tells how many such parts are following.

This part is 66 bytes in size.

char[4] {1, 3, 5, 0x81}
char[4] {0, 0, 0, 0}
char[2] {A, B}               (A<<8 + B).MTS = 00012.MTS, A=0, B=0x0C; 
char[1] {0x1E}
char[1] {C}                  C = BCD (Century)
char[1] {D}                  D = BCD (Decade)
char[1] {E}                  E = BCD (Month)
char[1] {F}                  F = BCD (Day)
char[1] {G}                  G = BCD (Hour)
char[1] {H}                  H = BCD (Minute)
char[1] {I}                  I = BCD (Second)
char[2] {0x90, 0x0A} or {0x90, 0x0C}
char[10]                     date as string (no time) e.g. '2010. 4.18'
char[2] {0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0, 0, 0, 0}
char[4] {0x11, 0x10, 0, 0}
char[4] {0, I, J, _}         I = 0x65 or 0x66; J=2 for SH or 0 for FHD
char[1] {0x03}
char[3] 'FHD'; 'SH\0'        video format
char[4] {0, 0, 0, 0}
char[4] {0xFF, 0xFF, 0xFF, 0xFF}
char[2] {0, 0}

A and B tell the name of the corresponding MTS file e.g. (A<<8 + B).MTS = 00012.MTS, A=0, B=0x0C

Trailer

This part is 50 bytes in size.

char[4] {0, 0, 0, 0}
char[4] {_, _, _, _}
...
char[4] {_, _, _, _}
char[4] {0, 0, 0, 0}
char[2] {0, 0}

Definitions

BCD
Binary Coded Decimal
_
unknow but different in different files
FHD
Full HD Quality (1080p25)
SH
Super High Quality (720p50)

Time Stamp Parser

This is a small C programm to parse all time stamps of MTS files that are written in playlist files in a directory. This programm is developed based on this file:

http://www.avsforum.com/avs-vb/showthread.php?p=14578210#post14578210

/* GPL 2.1 © Elte 2011 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>

#define VERSION         "0.1"
#define SIGNATUR        "MPLS0100"

typedef struct {
    unsigned char decade, month, day, hour, minute, second;
} MTS_date;

int main (int argc, char *argv[])
{
    struct dirent  *dp = NULL;
    DIR       *dir_ptr = NULL;
    FILE *mpl_file_ptr = NULL;

    int ret = 0;

    unsigned char signatur[] = SIGNATUR, buffer[sizeof(SIGNATUR)];

    if (argc != 2) {
        fprintf(stderr, "Version: %s\n", VERSION);
        fprintf(stderr, "Usage: %s <path to folder containing *.MPL files\n", argv[0]);
        goto ERROR;
    }

    if (chdir(argv[1]) == -1) {
	fprintf(stderr, "Cannot change directory: %s %s\n", argv[1], strerror(errno));
	goto ERROR;
    }

    if ((dir_ptr = opendir (".")) == NULL) {
        fprintf (stderr, "Error reading directory: %s %s\n", argv[1], strerror(errno));
        goto ERROR;
    }

//    printf (" STREAM       DATE       TIME\n");
//    printf ("---------  ----------  --------\n");

    while ((dp = readdir(dir_ptr)) != NULL) {

        if (!strncmp ((dp->d_name) + (strlen (dp->d_name) - 4), ".MPL", 4)) {

            unsigned char file_number[2] = {0, 0},
                                num_desc = 0;
            MTS_date                this = {0, 0, 0, 0, 0, 0};

            if ((mpl_file_ptr = fopen (dp->d_name, "r")) == NULL) {
                fprintf (stderr, "Error opening file: %s %s\n", dp->d_name, strerror(errno));
                goto NEXT_FILE;
            }

            if ((fread (buffer, sizeof(SIGNATUR), 1, mpl_file_ptr) != 1) ||
                (strncmp (buffer, SIGNATUR, sizeof(SIGNATUR)))) {
                fprintf (stderr, "Could not read file signatur. Wrong filetype?\n");
                goto NEXT_FILE;
            }

            // find out how many mts files are described
            // the 66th byte contains this number
            fseek (mpl_file_ptr, 66 - sizeof(SIGNATUR) - 1, SEEK_CUR);
            ret = fgetc(mpl_file_ptr);
            if (ret != EOF) {
                num_desc = (unsigned char) ret;
            } else {
                fprintf (stderr, "Could not read contents\n");
                goto NEXT_FILE;
            }

            // jump to the first occurance of a time stamp and print it
            // iterate till all num_desc time stamps are shown
            // trailer = 50 bytes
            // mts description = 66 bytes
            // actual info starts at 9th byte of mts description
            fseek (mpl_file_ptr, -50 - 66*num_desc - 48 +2, SEEK_END);

            while (num_desc > 0) {

                int i;
                const unsigned char time_stamp_sig[] = {1, 3, 5, 0x81, 0, 0, 0, 0};

                num_desc--;
                fseek (mpl_file_ptr, 48, SEEK_CUR);

                // scan for time stamp signatur
                for (i=0; i<8; i++) {
                    if ((ret = fgetc(mpl_file_ptr)) != time_stamp_sig[i]) {
                        fprintf (stderr, "Could not parse contents\n");
                        goto NEXT_FILE;
                    }
                }

                // scan time stamp
                if ((ret = fscanf (mpl_file_ptr, "%c%c\x1E%*1[ ]%c%c%c%c%c%c",
                              &file_number[0], &file_number[1],
                              &this.decade, &this.month, &this.day,
                              &this.hour, &this.minute, &this.second)) != 8) {
                    fprintf (stderr, "Could not parse time stamp\n");
                    goto NEXT_FILE;
                }
                printf ("%.5d.MTS  20%.2X/%.2X/%.2X  %.2X:%.2X:%.2X\n",
                        (file_number[0]<<8) + file_number[1],
                        this.decade, this.month, this.day,
                        this.hour, this.minute, this.second);
            }
NEXT_FILE:
            fclose (mpl_file_ptr);
        }
    }
ERROR:
    closedir (dir_ptr);
}