xref: /haiku/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp (revision 2e9d65abf52fdbb521310d1bbf3f5e0a4d0b9af5)
16ac391b3SStephan Aßmus /*
26ac391b3SStephan Aßmus  * Copyright 2009, Stephan Aßmus <superstippi@gmx.de>
36ac391b3SStephan Aßmus  * All rights reserved. Distributed under the terms of the GNU L-GPL license.
46ac391b3SStephan Aßmus  */
56ac391b3SStephan Aßmus 
66ac391b3SStephan Aßmus #include "AVFormatWriter.h"
76ac391b3SStephan Aßmus 
86ac391b3SStephan Aßmus #include <stdio.h>
96ac391b3SStephan Aßmus #include <string.h>
106ac391b3SStephan Aßmus #include <stdlib.h>
116ac391b3SStephan Aßmus 
126ac391b3SStephan Aßmus #include <new>
136ac391b3SStephan Aßmus 
146ac391b3SStephan Aßmus #include <AutoDeleter.h>
156ac391b3SStephan Aßmus #include <Autolock.h>
166ac391b3SStephan Aßmus #include <ByteOrder.h>
176ac391b3SStephan Aßmus #include <DataIO.h>
186ac391b3SStephan Aßmus #include <MediaDefs.h>
196ac391b3SStephan Aßmus #include <MediaFormats.h>
206ac391b3SStephan Aßmus 
216ac391b3SStephan Aßmus extern "C" {
226ac391b3SStephan Aßmus 	#include "avformat.h"
236ac391b3SStephan Aßmus }
246ac391b3SStephan Aßmus 
256ac391b3SStephan Aßmus #include "DemuxerTable.h"
266ac391b3SStephan Aßmus #include "gfx_util.h"
276ac391b3SStephan Aßmus 
286ac391b3SStephan Aßmus 
296ac391b3SStephan Aßmus #define TRACE_AVFORMAT_WRITER
306ac391b3SStephan Aßmus #ifdef TRACE_AVFORMAT_WRITER
316ac391b3SStephan Aßmus #	define TRACE printf
326ac391b3SStephan Aßmus #	define TRACE_IO(a...)
336ac391b3SStephan Aßmus #	define TRACE_PACKET(a...)
346ac391b3SStephan Aßmus #else
356ac391b3SStephan Aßmus #	define TRACE(a...)
366ac391b3SStephan Aßmus #	define TRACE_IO(a...)
376ac391b3SStephan Aßmus #	define TRACE_PACKET(a...)
386ac391b3SStephan Aßmus #endif
396ac391b3SStephan Aßmus 
406ac391b3SStephan Aßmus #define ERROR(a...) fprintf(stderr, a)
416ac391b3SStephan Aßmus 
426ac391b3SStephan Aßmus 
436ac391b3SStephan Aßmus // #pragma mark - AVFormatWriter::StreamCookie
446ac391b3SStephan Aßmus 
456ac391b3SStephan Aßmus 
466ac391b3SStephan Aßmus class AVFormatWriter::StreamCookie {
476ac391b3SStephan Aßmus public:
486ac391b3SStephan Aßmus 								StreamCookie(BPositionIO* target,
496ac391b3SStephan Aßmus 									BLocker* streamLock);
506ac391b3SStephan Aßmus 	virtual						~StreamCookie();
516ac391b3SStephan Aßmus 
526ac391b3SStephan Aßmus private:
536ac391b3SStephan Aßmus 			BPositionIO*		fTarget;
546ac391b3SStephan Aßmus 			off_t				fPosition;
556ac391b3SStephan Aßmus 			// Since different threads may read from the source,
566ac391b3SStephan Aßmus 			// we need to protect the file position and I/O by a lock.
576ac391b3SStephan Aßmus 			BLocker*			fStreamLock;
586ac391b3SStephan Aßmus };
596ac391b3SStephan Aßmus 
606ac391b3SStephan Aßmus 
616ac391b3SStephan Aßmus 
626ac391b3SStephan Aßmus AVFormatWriter::StreamCookie::StreamCookie(BPositionIO* target,
636ac391b3SStephan Aßmus 		BLocker* streamLock)
646ac391b3SStephan Aßmus 	:
656ac391b3SStephan Aßmus 	fTarget(target),
666ac391b3SStephan Aßmus 	fPosition(0),
676ac391b3SStephan Aßmus 	fStreamLock(streamLock)
686ac391b3SStephan Aßmus {
696ac391b3SStephan Aßmus }
706ac391b3SStephan Aßmus 
716ac391b3SStephan Aßmus 
726ac391b3SStephan Aßmus AVFormatWriter::StreamCookie::~StreamCookie()
736ac391b3SStephan Aßmus {
746ac391b3SStephan Aßmus }
756ac391b3SStephan Aßmus 
766ac391b3SStephan Aßmus 
776ac391b3SStephan Aßmus // #pragma mark - AVFormatWriter
786ac391b3SStephan Aßmus 
796ac391b3SStephan Aßmus 
806ac391b3SStephan Aßmus AVFormatWriter::AVFormatWriter()
816ac391b3SStephan Aßmus 	:
826ac391b3SStephan Aßmus 	fStreams(NULL),
836ac391b3SStephan Aßmus 	fStreamLock("stream lock")
846ac391b3SStephan Aßmus {
856ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::AVFormatWriter\n");
866ac391b3SStephan Aßmus }
876ac391b3SStephan Aßmus 
886ac391b3SStephan Aßmus 
896ac391b3SStephan Aßmus AVFormatWriter::~AVFormatWriter()
906ac391b3SStephan Aßmus {
916ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::~AVFormatWriter\n");
926ac391b3SStephan Aßmus 	if (fStreams != NULL) {
936ac391b3SStephan Aßmus 		delete fStreams[0];
946ac391b3SStephan Aßmus 		delete[] fStreams;
956ac391b3SStephan Aßmus 	}
966ac391b3SStephan Aßmus }
976ac391b3SStephan Aßmus 
986ac391b3SStephan Aßmus 
996ac391b3SStephan Aßmus // #pragma mark -
1006ac391b3SStephan Aßmus 
1016ac391b3SStephan Aßmus 
1026ac391b3SStephan Aßmus status_t
1036ac391b3SStephan Aßmus AVFormatWriter::SetCopyright(const char* copyright)
1046ac391b3SStephan Aßmus {
1056ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::SetCopyright(%s)\n", copyright);
1066ac391b3SStephan Aßmus 
1076ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
1086ac391b3SStephan Aßmus }
1096ac391b3SStephan Aßmus 
1106ac391b3SStephan Aßmus 
1116ac391b3SStephan Aßmus status_t
1126ac391b3SStephan Aßmus AVFormatWriter::CommitHeader()
1136ac391b3SStephan Aßmus {
1146ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::CommitHeader\n");
1156ac391b3SStephan Aßmus 
1166ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
1176ac391b3SStephan Aßmus }
1186ac391b3SStephan Aßmus 
1196ac391b3SStephan Aßmus 
1206ac391b3SStephan Aßmus status_t
1216ac391b3SStephan Aßmus AVFormatWriter::Flush()
1226ac391b3SStephan Aßmus {
1236ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::Flush\n");
1246ac391b3SStephan Aßmus 
1256ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
1266ac391b3SStephan Aßmus }
1276ac391b3SStephan Aßmus 
1286ac391b3SStephan Aßmus 
1296ac391b3SStephan Aßmus status_t
1306ac391b3SStephan Aßmus AVFormatWriter::Close()
1316ac391b3SStephan Aßmus {
1326ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::Close\n");
1336ac391b3SStephan Aßmus 
1346ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
1356ac391b3SStephan Aßmus }
1366ac391b3SStephan Aßmus 
1376ac391b3SStephan Aßmus 
1386ac391b3SStephan Aßmus status_t
1396ac391b3SStephan Aßmus AVFormatWriter::AllocateCookie(void** _cookie)
1406ac391b3SStephan Aßmus {
1416ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::AllocateCookie()\n");
1426ac391b3SStephan Aßmus 
1436ac391b3SStephan Aßmus 	BAutolock _(fStreamLock);
1446ac391b3SStephan Aßmus 
1456ac391b3SStephan Aßmus 	if (fStreams == NULL)
1466ac391b3SStephan Aßmus 		return B_NO_INIT;
1476ac391b3SStephan Aßmus 
1486ac391b3SStephan Aßmus 	if (_cookie == NULL)
1496ac391b3SStephan Aßmus 		return B_BAD_VALUE;
1506ac391b3SStephan Aßmus 
1516ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
1526ac391b3SStephan Aßmus }
1536ac391b3SStephan Aßmus 
1546ac391b3SStephan Aßmus 
1556ac391b3SStephan Aßmus status_t
1566ac391b3SStephan Aßmus AVFormatWriter::FreeCookie(void* _cookie)
1576ac391b3SStephan Aßmus {
1586ac391b3SStephan Aßmus 	BAutolock _(fStreamLock);
1596ac391b3SStephan Aßmus 
1606ac391b3SStephan Aßmus 	StreamCookie* cookie = reinterpret_cast<StreamCookie*>(_cookie);
1616ac391b3SStephan Aßmus 
1626ac391b3SStephan Aßmus 	if (cookie != NULL) {
1636ac391b3SStephan Aßmus //		if (fStreams != NULL)
1646ac391b3SStephan Aßmus //			fStreams[cookie->VirtualIndex()] = NULL;
1656ac391b3SStephan Aßmus 		delete cookie;
1666ac391b3SStephan Aßmus 	}
1676ac391b3SStephan Aßmus 
1686ac391b3SStephan Aßmus 	return B_OK;
1696ac391b3SStephan Aßmus }
1706ac391b3SStephan Aßmus 
1716ac391b3SStephan Aßmus 
1726ac391b3SStephan Aßmus // #pragma mark -
1736ac391b3SStephan Aßmus 
1746ac391b3SStephan Aßmus 
1756ac391b3SStephan Aßmus status_t
176fa770e4cSStephan Aßmus AVFormatWriter::SetCopyright(void* cookie, const char* copyright)
177fa770e4cSStephan Aßmus {
178fa770e4cSStephan Aßmus 	TRACE("AVFormatWriter::SetCopyright(%p, %s)\n", cookie, copyright);
179fa770e4cSStephan Aßmus 
180fa770e4cSStephan Aßmus 	return B_NOT_SUPPORTED;
181fa770e4cSStephan Aßmus }
182fa770e4cSStephan Aßmus 
183fa770e4cSStephan Aßmus 
184fa770e4cSStephan Aßmus status_t
1856ac391b3SStephan Aßmus AVFormatWriter::AddTrackInfo(void* cookie, uint32 code,
1866ac391b3SStephan Aßmus 	const void* data, size_t size, uint32 flags)
1876ac391b3SStephan Aßmus {
1886ac391b3SStephan Aßmus 	TRACE("AVFormatWriter::AddTrackInfo(%lu, %p, %ld, %lu)\n",
1896ac391b3SStephan Aßmus 		code, data, size, flags);
1906ac391b3SStephan Aßmus 
1916ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
1926ac391b3SStephan Aßmus }
1936ac391b3SStephan Aßmus 
1946ac391b3SStephan Aßmus 
1956ac391b3SStephan Aßmus status_t
196c98ea335SStephan Aßmus AVFormatWriter::WriteChunk(void* cookie, const void* chunkBuffer,
197fa770e4cSStephan Aßmus 	size_t chunkSize, media_encode_info* encodeInfo)
1986ac391b3SStephan Aßmus {
199fa770e4cSStephan Aßmus 	TRACE("AVFormatWriter::WriteChunk(%p, %ld, %p)\n", chunkBuffer, chunkSize,
200fa770e4cSStephan Aßmus 		encodeInfo);
2016ac391b3SStephan Aßmus 
2026ac391b3SStephan Aßmus 	return B_NOT_SUPPORTED;
2036ac391b3SStephan Aßmus }
2046ac391b3SStephan Aßmus 
2056ac391b3SStephan Aßmus 
206*2e9d65abSStephan Aßmus // #pragma mark -
207*2e9d65abSStephan Aßmus 
208*2e9d65abSStephan Aßmus 
209*2e9d65abSStephan Aßmus /*static*/ int
210*2e9d65abSStephan Aßmus AVFormatWriter::_Write(void* cookie, const uint8* buffer, int bufferSize)
211*2e9d65abSStephan Aßmus {
212*2e9d65abSStephan Aßmus 	TRACE_IO("AVFormatWriter::_Write(%p, %p, %d)\n",
213*2e9d65abSStephan Aßmus 		cookie, buffer, bufferSize);
214*2e9d65abSStephan Aßmus 
215*2e9d65abSStephan Aßmus 	AVFormatWriter* writer = reinterpret_cast<AVFormatWriter*>(cookie);
216*2e9d65abSStephan Aßmus 
217*2e9d65abSStephan Aßmus 	ssize_t written = writer->fTarget->Write(buffer, bufferSize);
218*2e9d65abSStephan Aßmus 
219*2e9d65abSStephan Aßmus 	TRACE_IO("  written: %ld\n", written);
220*2e9d65abSStephan Aßmus 	return (int)written;
221*2e9d65abSStephan Aßmus 
222*2e9d65abSStephan Aßmus }
223*2e9d65abSStephan Aßmus 
224*2e9d65abSStephan Aßmus 
225*2e9d65abSStephan Aßmus /*static*/ off_t
226*2e9d65abSStephan Aßmus AVFormatWriter::_Seek(void* cookie, off_t offset, int whence)
227*2e9d65abSStephan Aßmus {
228*2e9d65abSStephan Aßmus 	TRACE_IO("AVFormatWriter::_Seek(%p, %lld, %d)\n",
229*2e9d65abSStephan Aßmus 		cookie, offset, whence);
230*2e9d65abSStephan Aßmus 
231*2e9d65abSStephan Aßmus 	AVFormatWriter* writer = reinterpret_cast<AVFormatWriter*>(cookie);
232*2e9d65abSStephan Aßmus 
233*2e9d65abSStephan Aßmus 	BPositionIO* positionIO = dynamic_cast<BPositionIO*>(writer->fTarget);
234*2e9d65abSStephan Aßmus 	if (positionIO == NULL)
235*2e9d65abSStephan Aßmus 		return -1;
236*2e9d65abSStephan Aßmus 
237*2e9d65abSStephan Aßmus 	// Support for special file size retrieval API without seeking
238*2e9d65abSStephan Aßmus 	// anywhere:
239*2e9d65abSStephan Aßmus 	if (whence == AVSEEK_SIZE) {
240*2e9d65abSStephan Aßmus 		off_t size;
241*2e9d65abSStephan Aßmus 		if (positionIO->GetSize(&size) == B_OK)
242*2e9d65abSStephan Aßmus 			return size;
243*2e9d65abSStephan Aßmus 		return -1;
244*2e9d65abSStephan Aßmus 	}
245*2e9d65abSStephan Aßmus 
246*2e9d65abSStephan Aßmus 	off_t position = positionIO->Seek(offset, whence);
247*2e9d65abSStephan Aßmus 	TRACE_IO("  position: %lld\n", position);
248*2e9d65abSStephan Aßmus 	if (position < 0)
249*2e9d65abSStephan Aßmus 		return -1;
250*2e9d65abSStephan Aßmus 
251*2e9d65abSStephan Aßmus 	return position;
252*2e9d65abSStephan Aßmus }
253*2e9d65abSStephan Aßmus 
254*2e9d65abSStephan Aßmus 
255