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
29 static int mpeg_write_header (SF_PRIVATE *psf, int calc_length) ;
30 static int mpeg_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
31
32 /*------------------------------------------------------------------------------
33 * Private functions
34 */
35
36 static int
mpeg_write_header(SF_PRIVATE * psf,int UNUSED (calc_length))37 mpeg_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
45 static int
mpeg_command(SF_PRIVATE * psf,int command,void * data,int datasize)46 mpeg_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
90 int
mpeg_init(SF_PRIVATE * psf,int bitrate_mode,int write_metadata)91 mpeg_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
129 int
mpeg_open(SF_PRIVATE * psf)130 mpeg_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
151 int
mpeg_init(SF_PRIVATE * psf,int UNUSED (bitrate_mode),int UNUSED (write_metadata))152 mpeg_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
158 int
mpeg_open(SF_PRIVATE * psf)159 mpeg_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