xref: /third_party/libsnd/src/mpeg.c (revision b815c7f3)
1/*
2** Copyright (C) 2019 Erik de Castro Lopo <erikd@mega-nerd.com>
3** Copyright (C) 2021 Arthur Taylor <art@ified.ca>
4**
5** This program is free software ; you can redistribute it and/or modify
6** it under the terms of the GNU Lesser General Public License as published by
7** the Free Software Foundation ; either version 2.1 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY ; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13** GNU Lesser General Public License for more details.
14**
15** You should have received a copy of the GNU Lesser General Public License
16** along with this program ; if not, write to the Free Software
17** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*/
19
20#include	"sfconfig.h"
21
22#include	"sndfile.h"
23#include	"common.h"
24
25#if HAVE_MPEG
26
27#include "mpeg.h"
28
29static int	mpeg_write_header (SF_PRIVATE *psf, int calc_length) ;
30static int	mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
31
32/*------------------------------------------------------------------------------
33 * Private functions
34 */
35
36static int
37mpeg_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
38{
39	if (psf->have_written)
40		return 0 ;
41
42	return mpeg_l3_encoder_write_id3tag (psf) ;
43}
44
45static int
46mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize)
47{	int bitrate_mode ;
48
49	switch (command)
50	{	case SFC_SET_COMPRESSION_LEVEL :
51			if (data == NULL || datasize != sizeof (double))
52			{	psf->error = SFE_BAD_COMMAND_PARAM ;
53				return SF_FALSE ;
54				} ;
55			if (psf->file.mode != SFM_WRITE)
56			{	psf->error = SFE_NOT_WRITEMODE ;
57				return SF_FALSE ;
58				} ;
59			return mpeg_l3_encoder_set_quality (psf, *(double *) data) ;
60
61		case SFC_SET_BITRATE_MODE :
62			if (psf->file.mode != SFM_WRITE)
63			{	psf->error = SFE_NOT_WRITEMODE ;
64				return SF_FALSE ;
65				} ;
66			if (data == NULL || datasize != sizeof (int))
67			{	psf->error = SFE_BAD_COMMAND_PARAM ;
68				return SF_FALSE ;
69				} ;
70			bitrate_mode = *(int *) data ;
71			return mpeg_l3_encoder_set_bitrate_mode (psf, bitrate_mode) ;
72
73		case SFC_GET_BITRATE_MODE :
74			if (psf->file.mode == SFM_READ)
75				return mpeg_decoder_get_bitrate_mode (psf) ;
76			else
77				return mpeg_l3_encoder_get_bitrate_mode (psf) ;
78
79		default :
80			return SF_FALSE ;
81		} ;
82
83	return SF_FALSE ;
84} /* mpeg_command */
85
86/*------------------------------------------------------------------------------
87 * Public functions
88 */
89
90int
91mpeg_init (SF_PRIVATE *psf, int bitrate_mode, int write_metadata)
92{	int error ;
93
94	if (psf->file.mode == SFM_RDWR)
95		return SFE_BAD_MODE_RW ;
96
97	if (psf->file.mode == SFM_WRITE)
98	{	switch (SF_CODEC (psf->sf.format))
99		{	case SF_FORMAT_MPEG_LAYER_III :
100				if ((error = mpeg_l3_encoder_init (psf, write_metadata)))
101					return error ;
102				mpeg_l3_encoder_set_bitrate_mode (psf, bitrate_mode) ;
103				if (write_metadata)
104				{	/* ID3 support */
105					psf->strings.flags = SF_STR_ALLOW_START ;
106					psf->write_header = mpeg_write_header ;
107					} ;
108				break ;
109
110			case SF_FORMAT_MPEG_LAYER_I :
111			case SF_FORMAT_MPEG_LAYER_II :
112				psf_log_printf (psf, "MPEG Layer I and II encoding is not yet supported.\n") ;
113				return SFE_UNIMPLEMENTED ;
114
115			default:
116				psf_log_printf (psf, "%s: bad psf->sf.format 0x%x.\n", __func__, psf->sf.format) ;
117				return SFE_INTERNAL ;
118			} ;
119		} ;
120
121	if (psf->file.mode == SFM_READ)
122	{	if ((error = mpeg_decoder_init (psf)))
123			return error ;
124		} ;
125
126	return 0 ;
127} /* mpeg_init */
128
129int
130mpeg_open (SF_PRIVATE *psf)
131{	int error ;
132
133	/* Choose variable bitrate mode by default for standalone files.*/
134	if ((error = mpeg_init (psf, SF_BITRATE_MODE_VARIABLE, SF_TRUE)))
135		return error ;
136
137	psf->dataoffset = 0 ;
138	psf->command = mpeg_command ;
139
140	if (psf->filelength != SF_COUNT_MAX)
141		psf->datalength = psf->filelength - psf->dataoffset ;
142	else
143		psf->datalength = SF_COUNT_MAX ;
144
145
146	return 0 ;
147} /* mpeg_open */
148
149#else /* HAVE_MPEG */
150
151int
152mpeg_init (SF_PRIVATE *psf, int UNUSED (bitrate_mode) , int UNUSED (write_metadata))
153{
154	psf_log_printf (psf, "This version of libsndfile was compiled without MPEG support.\n") ;
155	return SFE_UNIMPLEMENTED ;
156} /* mpeg_init */
157
158int
159mpeg_open (SF_PRIVATE *psf)
160{
161	psf_log_printf (psf, "This version of libsndfile was compiled without MP3 support.\n") ;
162	return SFE_UNIMPLEMENTED ;
163} /* mpeg_open */
164
165#endif
166