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
18MediaFileInfo::MediaFileInfo(BMediaFile* file)
19{
20	LoadInfo(file);
21}
22
23
24status_t
25MediaFileInfo::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
152void
153MediaFileInfo::_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