1/*
2 * Copyright 2010-2011, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan Aßmus <superstippi@gmx.de>
7 * 		SHINTA
8 */
9#include "MediaFileTrackSupplier.h"
10
11#include <new>
12
13#include <stdio.h>
14#include <string.h>
15
16#include <MediaFile.h>
17#include <MediaTrack.h>
18#include <String.h>
19
20#include "MediaTrackAudioSupplier.h"
21#include "MediaTrackVideoSupplier.h"
22#include "ImageTrackVideoSupplier.h"
23
24
25MediaFileTrackSupplier::MediaFileTrackSupplier()
26	:
27	TrackSupplier()
28{
29}
30
31
32MediaFileTrackSupplier::~MediaFileTrackSupplier()
33{
34	for (vector<BMediaFile*>::size_type i = fMediaFiles.size() - 1;
35		static_cast<int32>(i) >= 0; i--) {
36		delete fMediaFiles[i];
37		// BMediaFile destructor will call ReleaseAllTracks()
38	}
39
40	for (vector<BBitmap*>::size_type i = fBitmaps.size() - 1;
41		static_cast<int32>(i) >= 0; i--) {
42		delete fBitmaps[i];
43	}
44
45 	for (int32 i = fSubTitleTracks.CountItems() - 1; i >= 0; i--)
46 		delete reinterpret_cast<SubTitles*>(fSubTitleTracks.ItemAtFast(i));
47 }
48
49
50status_t
51MediaFileTrackSupplier::InitCheck()
52{
53	if (fMediaFiles.empty())
54		return B_ERROR;
55
56	return fMediaFiles[0]->InitCheck();
57}
58
59
60status_t
61MediaFileTrackSupplier::GetFileFormatInfo(media_file_format* fileFormat)
62{
63	if (fMediaFiles.empty())
64		return B_ERROR;
65
66	return fMediaFiles[0]->GetFileFormatInfo(fileFormat);
67}
68
69
70status_t
71MediaFileTrackSupplier::GetCopyright(BString* copyright)
72{
73	if (fMediaFiles.empty())
74		return B_ERROR;
75
76	*copyright = fMediaFiles[0]->Copyright();
77	return B_OK;
78}
79
80
81status_t
82MediaFileTrackSupplier::GetMetaData(BMessage* metaData)
83{
84	if (fMediaFiles.empty())
85		return B_ERROR;
86
87	return fMediaFiles[0]->GetMetaData(metaData);
88}
89
90
91int32
92MediaFileTrackSupplier::CountAudioTracks()
93{
94	return fAudioTracks.CountItems();
95}
96
97
98int32
99MediaFileTrackSupplier::CountVideoTracks()
100{
101	return fVideoTracks.CountItems() + fBitmaps.size();
102}
103
104
105int32
106MediaFileTrackSupplier::CountSubTitleTracks()
107{
108	return fSubTitleTracks.CountItems();
109}
110
111
112status_t
113MediaFileTrackSupplier::GetAudioMetaData(int32 index, BMessage* metaData)
114{
115	BMediaTrack* track = (BMediaTrack*)fAudioTracks.ItemAt(index);
116	if (track == NULL)
117		return B_BAD_INDEX;
118
119	return track->GetMetaData(metaData);
120}
121
122
123status_t
124MediaFileTrackSupplier::GetVideoMetaData(int32 index, BMessage* metaData)
125{
126	BMediaTrack* track = (BMediaTrack*)fVideoTracks.ItemAt(index);
127	if (track == NULL)
128		return B_BAD_INDEX;
129
130	return track->GetMetaData(metaData);
131}
132
133
134AudioTrackSupplier*
135MediaFileTrackSupplier::CreateAudioTrackForIndex(int32 index)
136{
137	BMediaTrack* track = (BMediaTrack*)fAudioTracks.ItemAt(index);
138	if (track == NULL)
139		return NULL;
140
141	return new(std::nothrow) MediaTrackAudioSupplier(track, index);
142}
143
144
145VideoTrackSupplier*
146MediaFileTrackSupplier::CreateVideoTrackForIndex(int32 index)
147{
148	VideoTrackSupplier* supplier;
149	status_t initStatus;
150
151	if (fVideoTracks.CountItems() <= index
152			&& index < fVideoTracks.CountItems() + static_cast<int32>(fBitmaps.size())) {
153		supplier = new(std::nothrow) ImageTrackVideoSupplier(
154			fBitmaps[index - fVideoTracks.CountItems()], index, initStatus);
155	} else {
156		BMediaTrack* track = (BMediaTrack*)fVideoTracks.ItemAt(index);
157		if (track == NULL)
158			return NULL;
159
160		supplier = new(std::nothrow) MediaTrackVideoSupplier(track, index,
161			initStatus);
162	}
163
164	if (initStatus != B_OK) {
165		delete supplier;
166		return NULL;
167	}
168	return supplier;
169}
170
171
172const SubTitles*
173MediaFileTrackSupplier::SubTitleTrackForIndex(int32 index)
174{
175	return reinterpret_cast<SubTitles*>(fSubTitleTracks.ItemAt(index));
176}
177
178
179bool
180MediaFileTrackSupplier::AddSubTitles(SubTitles* subTitles)
181{
182	return fSubTitleTracks.AddItem(subTitles);
183}
184
185
186status_t
187MediaFileTrackSupplier::AddMediaFile(BMediaFile* mediaFile)
188{
189	if (mediaFile->InitCheck() != B_OK)
190		return B_ERROR;
191	int trackCount = mediaFile->CountTracks();
192	if (trackCount <= 0)
193		return B_ERROR;
194
195	status_t	funcStatus = B_ERROR;
196	for (int i = 0; i < trackCount; i++) {
197		BMediaTrack* track = mediaFile->TrackAt(i);
198		media_format format;
199		status_t status = track->EncodedFormat(&format);
200		if (status != B_OK) {
201			fprintf(stderr, "MediaFileTrackSupplier: EncodedFormat failed for "
202				"track index %d, error: %s\n", i, strerror(status));
203			mediaFile->ReleaseTrack(track);
204			continue;
205		}
206
207		if (track->Duration() <= 0) {
208			fprintf(stderr, "MediaFileTrackSupplier: warning! track index %d "
209				"has no duration\n", i);
210		}
211
212		if (format.IsAudio()) {
213			if (fAudioTracks.AddItem(track)) {
214				funcStatus = B_OK;
215			} else {
216				mediaFile->ReleaseTrack(track);
217			}
218		} else if (format.IsVideo()) {
219			if (fVideoTracks.AddItem(track)) {
220				funcStatus = B_OK;
221			} else {
222				mediaFile->ReleaseTrack(track);
223			}
224		} else {
225			printf("MediaFileTrackSupplier: track index %d has unknown "
226				"type\n", i);
227			mediaFile->ReleaseTrack(track);
228		}
229	}
230	if (funcStatus == B_OK)
231		fMediaFiles.push_back(mediaFile);
232	return funcStatus;
233}
234
235
236status_t
237MediaFileTrackSupplier::AddBitmap(BBitmap* bitmap)
238{
239	fBitmaps.push_back(bitmap);
240	return B_OK;
241}
242
243
244