1 // Copyright 1999, Be Incorporated. All Rights Reserved.
2 // Copyright 2000-2004, Jun Suzuki. All Rights Reserved.
3 // Copyright 2007, Stephan Aßmus. All Rights Reserved.
4 // Copyright 2010, Haiku, Inc. All Rights Reserved.
5 // This file may be used under the terms of the Be Sample Code License.
6
7
8 #include "MediaFileInfo.h"
9
10 #include <Catalog.h>
11 #include <MediaTrack.h>
12 #include <StringFormat.h>
13 #include <stdio.h>
14
15 #undef B_TRANSLATION_CONTEXT
16 #define B_TRANSLATION_CONTEXT "MediaFileInfo"
17
MediaFileInfo(BMediaFile * file)18 MediaFileInfo::MediaFileInfo(BMediaFile* file)
19 {
20 LoadInfo(file);
21 }
22
23
24 status_t
LoadInfo(BMediaFile * file)25 MediaFileInfo::LoadInfo(BMediaFile* file)
26 {
27 _Reset();
28 if (!file)
29 return B_BAD_VALUE;
30
31 BMediaTrack* track;
32 media_format format;
33 format.Clear();
34 media_codec_info codecInfo;
35 bool audioDone(false), videoDone(false);
36 bigtime_t audioDuration = 0;
37 bigtime_t videoDuration = 0;
38 int32 tracks = file->CountTracks();
39 int64 videoFrames = 0;
40 int64 audioFrames = 0;
41 status_t ret = B_OK;
42
43 for (int32 i = 0; i < tracks && (!audioDone || !videoDone); i++) {
44 track = file->TrackAt(i);
45 if (track == NULL)
46 return B_ERROR;
47
48 ret = track->InitCheck();
49 if (ret != B_OK)
50 return ret;
51
52 ret = track->EncodedFormat(&format);
53 if (ret != B_OK)
54 return ret;
55
56 static BStringFormat frameFormat(B_TRANSLATE(
57 "{0, plural, one{# frame} other{# frames}}"));
58
59 if (format.IsVideo()) {
60 format.Clear();
61 format.type = B_MEDIA_RAW_VIDEO;
62
63 ret = track->DecodedFormat(&format);
64 if (ret != B_OK)
65 return ret;
66
67 media_raw_video_format *rvf = &(format.u.raw_video);
68
69 ret = track->GetCodecInfo(&codecInfo);
70 if (ret != B_OK)
71 return ret;
72
73 video.format << codecInfo.pretty_name;
74 videoDuration = track->Duration();
75 videoFrames = track->CountFrames();
76
77 BString details;
78 details.SetToFormat(
79 B_TRANSLATE_COMMENT("%u × %u, %.2ffps", "Width × Height, fps;"
80 "The '×' is the Unicode multiplication sign U+00D7"),
81 (unsigned)format.Width(), (unsigned)format.Height(),
82 rvf->field_rate / rvf->interlace);
83
84 details << " / ";
85 frameFormat.Format(details, videoFrames);
86
87 video.details << details;
88 videoDone = true;
89
90 } else if (format.IsAudio()) {
91 format.Clear();
92 format.type = B_MEDIA_RAW_AUDIO;
93 ret = track->DecodedFormat(&format);
94 if (ret != B_OK)
95 return ret;
96 media_raw_audio_format *raf = &(format.u.raw_audio);
97 char bytesPerSample = (char)(raf->format & 0xf);
98
99 BString details;
100 if (bytesPerSample == 1 || bytesPerSample == 2) {
101 static BStringFormat bitFormat(
102 B_TRANSLATE("{0, plural, one{# bit} other{# bits}}"));
103 bitFormat.Format(details, bytesPerSample * 8);
104 details.SetToFormat(B_TRANSLATE("%d bit "), bytesPerSample * 8);
105 } else {
106 static BStringFormat bitFormat(
107 B_TRANSLATE("{0, plural, one{# byte} other{# bytes}}"));
108 bitFormat.Format(details, bytesPerSample);
109 }
110 audio.details << details;
111 audio.details << " ";
112
113 ret = track->GetCodecInfo(&codecInfo);
114 if (ret != B_OK)
115 return ret;
116
117 audio.format << codecInfo.pretty_name;
118 audioDuration = track->Duration();
119 audioFrames = track->CountFrames();
120 BString channels;
121 if (raf->channel_count == 1) {
122 channels.SetToFormat(B_TRANSLATE("%.1f kHz mono"),
123 raf->frame_rate / 1000.f);
124 } else if (raf->channel_count == 2) {
125 channels.SetToFormat(B_TRANSLATE("%.1f kHz stereo"),
126 raf->frame_rate / 1000.f);
127 } else {
128 channels.SetToFormat(B_TRANSLATE("%.1f kHz %ld channel"),
129 raf->frame_rate / 1000.f, (long int)raf->channel_count);
130 }
131
132 channels << " / ";
133 frameFormat.Format(channels, audioFrames);
134
135 audio.details << channels;
136
137 audioDone = true;
138 }
139 ret = file->ReleaseTrack(track);
140 if (ret != B_OK)
141 return ret;
142 }
143
144 useconds = MAX(audioDuration, videoDuration);
145 duration << (int32)(useconds / 1000000)
146 << B_TRANSLATE(" seconds");
147
148 return B_OK;
149 }
150
151
152 void
_Reset()153 MediaFileInfo::_Reset()
154 {
155 audio.details.SetTo("");
156 audio.format.SetTo("");
157 video.details.SetTo("");
158 video.format.SetTo("");
159 useconds = 0;
160 duration.SetTo("");
161 }
162